76#include "llvm/IR/IntrinsicsAArch64.h"
111#define DEBUG_TYPE "aarch64-lower"
114STATISTIC(NumOptimizedImms,
"Number of times immediates were optimized");
121 cl::desc(
"Allow AArch64 Local Dynamic TLS code generation"),
126 cl::desc(
"Enable AArch64 logical imm instruction "
136 cl::desc(
"Combine extends of AArch64 masked "
137 "gather intrinsics"),
141 cl::desc(
"Combine ext and trunc to TBL"),
156 cl::desc(
"Enable / disable SVE scalable vectors in Global ISel"),
160 "aarch64-br-merging-base-cost",
cl::init(2),
162 "Cost threshold for merging multiple conditionals into one branch "
163 "versus splitting into multiple branches: conditionals are merged when "
164 "their instruction cost is below this limit and split above it. Set to "
165 "-1 to never merge branches."),
169 "aarch64-br-merging-ccmp-bias",
cl::init(6),
170 cl::desc(
"Increases 'aarch64-br-merging-base-cost' to account for the "
171 "CCMP instruction, which is always available on AArch64 and "
172 "makes merging branch conditions cheaper."),
176 "aarch64-br-merging-cbz-tbnz-bias",
cl::init(6),
177 cl::desc(
"Decreases 'aarch64-br-merging-base-cost' when a condition can "
178 "lower to a single CBZ/CBNZ or TBZ/TBNZ compare-and-branch, to "
179 "bias toward splitting. Set to 0 to disable."),
183 "aarch64-br-merging-likely-bias",
cl::init(0),
184 cl::desc(
"Increases 'aarch64-br-merging-base-cost' when all conditionals "
185 "are likely to be executed, biasing toward merging. Set to -1 to "
186 "never merge likely branches."),
190 "aarch64-br-merging-unlikely-bias",
cl::init(-1),
192 "Decreases 'aarch64-br-merging-base-cost' when all conditionals are "
193 "unlikely to be executed, biasing toward splitting. Set to -1 to never "
194 "merge unlikely branches."),
201 cl::desc(
"Generate ISD::PTRADD nodes for pointer arithmetic in "
202 "SelectionDAG for FEAT_CPA"),
209 "aarch64-use-conditional-fpmr-write",
cl::Hidden,
210 cl::desc(
"Only write FPMR when the requested value differs from the "
218 cl::desc(
"Use SVE for fixed-length vector bfloat operations"),
228 AArch64::X3, AArch64::X4, AArch64::X5,
229 AArch64::X6, AArch64::X7};
231 AArch64::Q3, AArch64::Q4, AArch64::Q5,
232 AArch64::Q6, AArch64::Q7};
257 return MVT::nxv8bf16;
264 switch (EC.getKnownMinValue()) {
280 "Expected scalable predicate vector type!");
302 "Expected legal vector type!");
309 "Expected legal type!");
310 return VT == MVT::nxv16i1;
323 "Unexpected fixed-size unpacked type.");
333 case AArch64ISD::BITREVERSE_MERGE_PASSTHRU:
334 case AArch64ISD::BSWAP_MERGE_PASSTHRU:
335 case AArch64ISD::REVH_MERGE_PASSTHRU:
336 case AArch64ISD::REVW_MERGE_PASSTHRU:
337 case AArch64ISD::REVD_MERGE_PASSTHRU:
338 case AArch64ISD::CTLZ_MERGE_PASSTHRU:
339 case AArch64ISD::CTPOP_MERGE_PASSTHRU:
340 case AArch64ISD::DUP_MERGE_PASSTHRU:
341 case AArch64ISD::ABS_MERGE_PASSTHRU:
342 case AArch64ISD::NEG_MERGE_PASSTHRU:
343 case AArch64ISD::FNEG_MERGE_PASSTHRU:
344 case AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU:
345 case AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU:
346 case AArch64ISD::FCEIL_MERGE_PASSTHRU:
347 case AArch64ISD::FFLOOR_MERGE_PASSTHRU:
348 case AArch64ISD::FNEARBYINT_MERGE_PASSTHRU:
349 case AArch64ISD::FRINT_MERGE_PASSTHRU:
350 case AArch64ISD::FRINT32_MERGE_PASSTHRU:
351 case AArch64ISD::FRINT64_MERGE_PASSTHRU:
352 case AArch64ISD::FROUND_MERGE_PASSTHRU:
353 case AArch64ISD::FROUNDEVEN_MERGE_PASSTHRU:
354 case AArch64ISD::FTRUNC_MERGE_PASSTHRU:
355 case AArch64ISD::FTRUNC32_MERGE_PASSTHRU:
356 case AArch64ISD::FTRUNC64_MERGE_PASSTHRU:
357 case AArch64ISD::FP_ROUND_MERGE_PASSTHRU:
358 case AArch64ISD::FP_EXTEND_MERGE_PASSTHRU:
359 case AArch64ISD::SINT_TO_FP_MERGE_PASSTHRU:
360 case AArch64ISD::UINT_TO_FP_MERGE_PASSTHRU:
361 case AArch64ISD::FCVTX_MERGE_PASSTHRU:
362 case AArch64ISD::FCVTZU_MERGE_PASSTHRU:
363 case AArch64ISD::FCVTZS_MERGE_PASSTHRU:
364 case AArch64ISD::FSQRT_MERGE_PASSTHRU:
365 case AArch64ISD::FRECPX_MERGE_PASSTHRU:
366 case AArch64ISD::FABS_MERGE_PASSTHRU:
367 case AArch64ISD::STRICT_FCEIL_MERGE_PASSTHRU:
368 case AArch64ISD::STRICT_FFLOOR_MERGE_PASSTHRU:
369 case AArch64ISD::STRICT_FNEARBYINT_MERGE_PASSTHRU:
370 case AArch64ISD::STRICT_FROUND_MERGE_PASSTHRU:
371 case AArch64ISD::STRICT_FROUNDEVEN_MERGE_PASSTHRU:
372 case AArch64ISD::STRICT_FTRUNC_MERGE_PASSTHRU:
373 case AArch64ISD::STRICT_FSQRT_MERGE_PASSTHRU:
380 switch (
Op.getOpcode()) {
386 case AArch64ISD::PTRUE:
387 case AArch64ISD::SETCC_MERGE_ZERO:
390 switch (
Op.getConstantOperandVal(0)) {
393 case Intrinsic::aarch64_sve_ptrue:
394 case Intrinsic::aarch64_sve_pnext:
395 case Intrinsic::aarch64_sve_cmpeq:
396 case Intrinsic::aarch64_sve_cmpne:
397 case Intrinsic::aarch64_sve_cmpge:
398 case Intrinsic::aarch64_sve_cmpgt:
399 case Intrinsic::aarch64_sve_cmphs:
400 case Intrinsic::aarch64_sve_cmphi:
401 case Intrinsic::aarch64_sve_cmpeq_wide:
402 case Intrinsic::aarch64_sve_cmpne_wide:
403 case Intrinsic::aarch64_sve_cmpge_wide:
404 case Intrinsic::aarch64_sve_cmpgt_wide:
405 case Intrinsic::aarch64_sve_cmplt_wide:
406 case Intrinsic::aarch64_sve_cmple_wide:
407 case Intrinsic::aarch64_sve_cmphs_wide:
408 case Intrinsic::aarch64_sve_cmphi_wide:
409 case Intrinsic::aarch64_sve_cmplo_wide:
410 case Intrinsic::aarch64_sve_cmpls_wide:
411 case Intrinsic::aarch64_sve_fcmpeq:
412 case Intrinsic::aarch64_sve_fcmpne:
413 case Intrinsic::aarch64_sve_fcmpge:
414 case Intrinsic::aarch64_sve_fcmpgt:
415 case Intrinsic::aarch64_sve_fcmpuo:
416 case Intrinsic::aarch64_sve_facgt:
417 case Intrinsic::aarch64_sve_facge:
418 case Intrinsic::aarch64_sve_whilege:
419 case Intrinsic::aarch64_sve_whilegt:
420 case Intrinsic::aarch64_sve_whilehi:
421 case Intrinsic::aarch64_sve_whilehs:
422 case Intrinsic::aarch64_sve_whilele:
423 case Intrinsic::aarch64_sve_whilelo:
424 case Intrinsic::aarch64_sve_whilels:
425 case Intrinsic::aarch64_sve_whilelt:
426 case Intrinsic::aarch64_sve_match:
427 case Intrinsic::aarch64_sve_nmatch:
428 case Intrinsic::aarch64_sve_whilege_x2:
429 case Intrinsic::aarch64_sve_whilegt_x2:
430 case Intrinsic::aarch64_sve_whilehi_x2:
431 case Intrinsic::aarch64_sve_whilehs_x2:
432 case Intrinsic::aarch64_sve_whilele_x2:
433 case Intrinsic::aarch64_sve_whilelo_x2:
434 case Intrinsic::aarch64_sve_whilels_x2:
435 case Intrinsic::aarch64_sve_whilelt_x2:
441static std::tuple<SDValue, SDValue>
462 if (!ConstDiscN || !
isUInt<16>(ConstDiscN->getZExtValue()))
468 AddrDisc = DAG->
getRegister(AArch64::NoRegister, MVT::i64);
470 return std::make_tuple(
489 if (Subtarget->hasLS64()) {
495 if (Subtarget->hasFPARMv8()) {
504 if (Subtarget->hasNEON()) {
508 addDRType(MVT::v2f32);
509 addDRType(MVT::v8i8);
510 addDRType(MVT::v4i16);
511 addDRType(MVT::v2i32);
512 addDRType(MVT::v1i64);
513 addDRType(MVT::v1f64);
514 addDRType(MVT::v4f16);
515 addDRType(MVT::v4bf16);
517 addQRType(MVT::v4f32);
518 addQRType(MVT::v2f64);
519 addQRType(MVT::v16i8);
520 addQRType(MVT::v8i16);
521 addQRType(MVT::v4i32);
522 addQRType(MVT::v2i64);
523 addQRType(MVT::v8f16);
524 addQRType(MVT::v8bf16);
527 if (Subtarget->isSVEorStreamingSVEAvailable()) {
555 if (Subtarget->useSVEForFixedLengthVectors()) {
597 if (Subtarget->hasFPARMv8()) {
688 if (Subtarget->hasFPARMv8()) {
694 if (Subtarget->hasFPARMv8()) {
748 if (Subtarget->hasCSSC()) {
827 if (Subtarget->hasFullFP16()) {
859 if (Subtarget->hasFullFP16()) {
872 auto LegalizeNarrowFP = [
this](
MVT ScalarVT) {
980 if (!Subtarget->hasFullFP16()) {
981 LegalizeNarrowFP(MVT::f16);
983 LegalizeNarrowFP(MVT::bf16);
1001 for (
MVT Ty : {MVT::f32, MVT::f64})
1003 if (Subtarget->hasFullFP16())
1011 for (
MVT Ty : {MVT::f32, MVT::f64})
1013 if (Subtarget->hasFullFP16())
1026 for (
MVT Ty : {MVT::f16, MVT::bf16, MVT::f32, MVT::f64})
1028 if (!Subtarget->hasLSE() && !Subtarget->outlineAtomics()) {
1040 if (Subtarget->outlineAtomics() && !Subtarget->hasLSE()) {
1068 if (Subtarget->hasLSE128()) {
1082 if (Subtarget->hasLSE2()) {
1139 if (WideVT.getScalarSizeInBits() > NarrowVT.getScalarSizeInBits()) {
1145 if (Subtarget->hasFPARMv8()) {
1243 if (Subtarget->isSVEorStreamingSVEAvailable())
1277 if (!Subtarget->isTargetWindows())
1293 if (Subtarget->hasSME())
1296 if (Subtarget->isNeonAvailable()) {
1341 for (
auto VT : {MVT::v2i32, MVT::v2i64, MVT::v4i32})
1344 if (Subtarget->hasFullFP16()) {
1373 for (
auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
1382 for (
auto VT : {MVT::v1i64, MVT::v2i64}) {
1398 for (
MVT VT : { MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v1i64,
1399 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64 }) {
1406 for (
MVT VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
1417 for (
MVT VT : { MVT::v4f16, MVT::v2f32,
1418 MVT::v8f16, MVT::v4f32, MVT::v2f64 }) {
1419 if (VT.getVectorElementType() != MVT::f16 || Subtarget->hasFullFP16()) {
1428 if (Subtarget->hasFullFP16())
1431 for (
MVT VT : { MVT::v8i8, MVT::v4i16, MVT::v2i32,
1432 MVT::v16i8, MVT::v8i16, MVT::v4i32 }) {
1447 for (
MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v2i32, MVT::v4i32})
1457 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32) {
1467 if (VT == MVT::v4i16 || VT == MVT::v8i16 || VT == MVT::v2i32 ||
1468 VT == MVT::v4i32 || VT == MVT::v2i64)
1473 if (VT == MVT::v8i8 || VT == MVT::v16i8 || VT == MVT::v8i16 ||
1474 VT == MVT::v4i16 || VT == MVT::v2i32 || VT == MVT::v4i32)
1493 for (
MVT Ty : {MVT::v2f32, MVT::v4f32, MVT::v2f64})
1495 if (Subtarget->hasFullFP16())
1496 for (
MVT Ty : {MVT::v4f16, MVT::v8f16})
1502 for (
MVT Ty : {MVT::v2f32, MVT::v4f32, MVT::v2f64})
1504 if (Subtarget->hasFullFP16())
1505 for (
MVT Ty : {MVT::v4f16, MVT::v8f16})
1540 for (
MVT VT : { MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64 })
1543 for (
MVT VT : { MVT::v16f16, MVT::v8f32, MVT::v4f64 })
1566 if (Subtarget->hasDotProd()) {
1583 if (Subtarget->hasMatMulInt8()) {
1598 if (Subtarget->hasF16F32DOT() || Subtarget->hasFP16FML()) {
1605 if (Subtarget->hasBF16())
1607 MVT::v8bf16,
Legal);
1611 if (Subtarget->hasAES()) {
1623 if (VT.is128BitVector() || VT.is64BitVector()) {
1638 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
1648 if (Subtarget->isSVEorStreamingSVEAvailable()) {
1650 {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1, MVT::nxv1i1}) {
1657 for (
auto VT : {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1}) {
1664 if (Subtarget->hasSVE2() && Subtarget->isSVEAvailable()) {
1665 for (
MVT VT : {MVT::nxv16i1, MVT::nxv8i1})
1669 {MVT::v16i1, MVT::v8i1, MVT::v16i8, MVT::v8i8, MVT::v3i8, MVT::v4i8})
1675 if (Subtarget->isSVEorStreamingSVEAvailable() &&
1676 (Subtarget->hasSVE2p1() || Subtarget->hasSME2()))
1679 for (
auto VT : {MVT::v16i8, MVT::v8i8, MVT::v4i16, MVT::v2i32})
1682 for (
auto VT : {MVT::v8f16, MVT::v4f32, MVT::v2f64})
1686 if (Subtarget->isSVEorStreamingSVEAvailable()) {
1687 for (
auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64}) {
1734 if (Subtarget->hasSME2() && Subtarget->isStreaming())
1763 if (!Subtarget->isLittleEndian())
1766 if (Subtarget->hasSVE2() ||
1767 (Subtarget->hasSME() && Subtarget->isStreaming()))
1772 for (
auto VT : {MVT::nxv4i32, MVT::nxv2i64}) {
1778 for (
auto VT : {MVT::nxv8i8, MVT::nxv4i16, MVT::nxv2i32}) {
1784 for (
auto VT : {MVT::nxv2i16, MVT::nxv4i16, MVT::nxv2i32})
1788 { MVT::nxv2i8, MVT::nxv2i16, MVT::nxv2i32, MVT::nxv2i64, MVT::nxv4i8,
1789 MVT::nxv4i16, MVT::nxv4i32, MVT::nxv8i8, MVT::nxv8i16 })
1801 {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1, MVT::nxv1i1}) {
1815 if (VT != MVT::nxv16i1) {
1825 {MVT::v4f16, MVT::v8f16, MVT::v4bf16, MVT::v8bf16, MVT::v2f32,
1826 MVT::v4f32, MVT::v1f64, MVT::v2f64, MVT::v8i8, MVT::v16i8, MVT::v4i16,
1827 MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v1i64, MVT::v2i64}) {
1865 for (
auto VT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32,
1866 MVT::nxv4f32, MVT::nxv2f64}) {
1912 if (Subtarget->hasSME2() && Subtarget->isStreaming())
1971 for (
auto VT : {MVT::nxv2bf16, MVT::nxv4bf16, MVT::nxv8bf16}) {
1987 if (Subtarget->hasSME2() && Subtarget->isStreaming())
1995 if (Subtarget->hasSVEB16B16() &&
1996 Subtarget->isNonStreamingSVEorSME2Available()) {
1998 for (
auto VT : {MVT::v4bf16, MVT::v8bf16, MVT::nxv2bf16, MVT::nxv4bf16,
2021 if (!Subtarget->hasSVEB16B16() ||
2022 !Subtarget->isNonStreamingSVEorSME2Available()) {
2023 for (
MVT VT : {MVT::nxv2bf16, MVT::nxv4bf16, MVT::nxv8bf16}) {
2033 if (VT != MVT::nxv2bf16 && Subtarget->hasBF16())
2039 if (Subtarget->hasBF16() && Subtarget->isNeonAvailable())
2048 for (
auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
2049 MVT::v4i32, MVT::v1i64, MVT::v2i64}) {
2058 for (
auto VT : {MVT::v4i16, MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v1i64,
2072 for (
auto VT : {MVT::v1i64, MVT::v2i64}) {
2079 if (Subtarget->useSVEForFixedLengthVectors()) {
2082 VT, !Subtarget->isNeonAvailable()))
2083 addTypeForFixedLengthSVE(VT);
2087 VT, !Subtarget->isNeonAvailable()))
2088 addTypeForFixedLengthSVE(VT);
2092 for (
auto VT : {MVT::v8i8, MVT::v4i16})
2097 for (
auto VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
2099 for (
auto VT : {MVT::v8f16, MVT::v4f32, MVT::v8bf16})
2117 for (
auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
2118 MVT::v4i32, MVT::v2i64}) {
2125 for (
auto VT : {MVT::v4f16, MVT::v8f16, MVT::v4f32})
2148 for (
auto VT : {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1})
2155 if (Subtarget->enableSubRegLiveness() &&
2156 (Subtarget->hasSVE2p1() ||
2157 (Subtarget->hasSME2() && Subtarget->isStreaming()))) {
2184 if (Subtarget->isSVEorStreamingSVEAvailable()) {
2194 if (Subtarget->hasMatMulInt8()) {
2196 MVT::nxv16i8,
Legal);
2201 if (Subtarget->hasSVE2() || Subtarget->hasSME()) {
2211 MVT::nxv8f16,
Legal);
2215 if (!Subtarget->isNeonAvailable() ||
2216 (!Subtarget->hasF16F32DOT() && !Subtarget->hasFP16FML())) {
2225 if (Subtarget->hasSVEBitPerm() &&
2226 (Subtarget->isSVEAvailable() ||
2227 (Subtarget->isSVEorStreamingSVEAvailable() &&
2228 Subtarget->hasSSVE_BitPerm()))) {
2229 for (
auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64}) {
2236 if (Subtarget->hasBF16())
2238 MVT::nxv8bf16,
Legal);
2242 if (Subtarget->isSVEAvailable() ||
2243 (Subtarget->isSVEorStreamingSVEAvailable() && Subtarget->hasSME2p2())) {
2246 {MVT::nxv4i32, MVT::nxv2i64, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv2f64})
2248 for (
auto VT : {MVT::nxv2i8, MVT::nxv2i16, MVT::nxv2i32, MVT::nxv2i64,
2249 MVT::nxv2f32, MVT::nxv2f64, MVT::nxv4i8, MVT::nxv4i16,
2250 MVT::nxv4i32, MVT::nxv4f32}) {
2259 for (
auto VT : {MVT::v2i32, MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32,
2281 if (Subtarget->hasSVE2p2() || Subtarget->hasSME2p2()) {
2284 {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv8f16, MVT::nxv8bf16}) {
2291 for (
auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v4f16,
2292 MVT::v8f16, MVT::v4bf16, MVT::v8bf16})
2304 if (Subtarget->hasSVE2() ||
2305 (Subtarget->hasSME() && Subtarget->isStreaming())) {
2307 for (
auto VT : {MVT::v2i32, MVT::v4i16, MVT::v8i8, MVT::v16i8}) {
2311 for (
auto VT : {MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1, MVT::nxv16i1}) {
2318 if (Subtarget->isSVEAvailable()) {
2319 for (
auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64,
2320 MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32,
2321 MVT::nxv4f32, MVT::nxv2f64, MVT::nxv2bf16, MVT::nxv4bf16,
2322 MVT::nxv8bf16, MVT::v4f16, MVT::v8f16, MVT::v4bf16,
2323 MVT::v8bf16, MVT::v2f32, MVT::v4f32, MVT::v1f64,
2324 MVT::v2f64, MVT::v8i8, MVT::v16i8, MVT::v4i16,
2325 MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v1i64,
2331 for (
auto VT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32,
2332 MVT::nxv4f32, MVT::nxv2f64, MVT::v4f16, MVT::v8f16,
2333 MVT::v2f32, MVT::v4f32, MVT::v2f64})
2337 if (Subtarget->hasSVE2()) {
2355 if (Subtarget->hasMOPS() && Subtarget->hasMTE()) {
2362 if (Subtarget->hasSVE()) {
2376 if (Subtarget->isTargetWindows()) {
2396void AArch64TargetLowering::addTypeForNEON(
MVT VT) {
2406 if (VT == MVT::v2f32 || VT == MVT::v4f32 || VT == MVT::v2f64) {
2428 if (VT == MVT::v2f32 || VT == MVT::v4f32 || VT == MVT::v2f64 ||
2429 ((VT == MVT::v4bf16 || VT == MVT::v8bf16 || VT == MVT::v4f16 ||
2430 VT == MVT::v8f16) &&
2431 Subtarget->hasFullFP16()))
2456 if (VT != MVT::v8i8 && VT != MVT::v16i8)
2465 for (
unsigned Opcode :
2483 for (
unsigned Opcode :
2518 if (Subtarget->isLittleEndian()) {
2529 if (Subtarget->hasD128()) {
2547 if (!Subtarget->isSVEorStreamingSVEAvailable() ||
2563void AArch64TargetLowering::addTypeForFixedLengthSVE(
MVT VT) {
2588 while (InnerVT != VT) {
2602 while (InnerVT != VT) {
2611 bool PreferSVE = !PreferNEON && Subtarget->isSVEAvailable();
2632 if (Subtarget->hasMatMulInt8()) {
2749void AArch64TargetLowering::addDRType(
MVT VT) {
2751 if (Subtarget->isNeonAvailable())
2755void AArch64TargetLowering::addQRType(
MVT VT) {
2757 if (Subtarget->isNeonAvailable())
2774 Imm =
C->getZExtValue();
2782 case AArch64ISD::SQDMULH:
2794 return N->getOpcode() ==
Opc &&
2799 const APInt &Demanded,
2807 if (
Imm == 0 ||
Imm == Mask ||
2811 unsigned EltSize =
Size;
2828 ((InvertedImm << 1) | (InvertedImm >> (EltSize - 1) & 1)) &
2830 uint64_t Sum = RotatedImm + NonDemandedBits;
2831 bool Carry = NonDemandedBits & ~Sum & (1ULL << (EltSize - 1));
2832 uint64_t Ones = (Sum + Carry) & NonDemandedBits;
2833 NewImm = (
Imm | Ones) & Mask;
2861 while (EltSize <
Size) {
2862 NewImm |= NewImm << EltSize;
2868 "demanded bits should never be altered");
2869 assert(OldImm != NewImm &&
"the new imm shouldn't be equal to the old imm");
2872 EVT VT =
Op.getValueType();
2878 if (NewImm == 0 || NewImm == OrigMask) {
2903 EVT VT =
Op.getValueType();
2917 switch (
Op.getOpcode()) {
2921 NewOpc =
Size == 32 ? AArch64::ANDWri : AArch64::ANDXri;
2924 NewOpc =
Size == 32 ? AArch64::ORRWri : AArch64::ORRXri;
2927 NewOpc =
Size == 32 ? AArch64::EORWri : AArch64::EORXri;
2933 uint64_t
Imm =
C->getZExtValue();
2942 switch (
Op.getOpcode()) {
2945 case AArch64ISD::DUP: {
2948 if (
SrcOp.getValueSizeInBits() !=
Op.getScalarValueSizeInBits()) {
2949 assert(
SrcOp.getValueSizeInBits() >
Op.getScalarValueSizeInBits() &&
2950 "Expected DUP implicit truncation");
2955 case AArch64ISD::CSEL: {
2962 case AArch64ISD::CSNEG:
2963 case AArch64ISD::CSINC:
2964 case AArch64ISD::CSINV: {
2972 if (
Op.getOpcode() == AArch64ISD::CSINC)
2976 else if (
Op.getOpcode() == AArch64ISD::CSINV)
2978 else if (
Op.getOpcode() == AArch64ISD::CSNEG)
2981 Op.getScalarValueSizeInBits())));
2986 case AArch64ISD::BICi: {
2989 ~(
Op->getConstantOperandAPInt(1) <<
Op->getConstantOperandAPInt(2))
2990 .trunc(
Known.getBitWidth());
2995 case AArch64ISD::VLSHR: {
3002 case AArch64ISD::VASHR: {
3009 case AArch64ISD::VSHL: {
3016 case AArch64ISD::MOVI: {
3018 APInt(
Known.getBitWidth(),
Op->getConstantOperandVal(0)));
3021 case AArch64ISD::MOVIshift: {
3023 APInt(
Known.getBitWidth(),
Op->getConstantOperandVal(0)
3024 <<
Op->getConstantOperandVal(1)));
3027 case AArch64ISD::MOVImsl: {
3030 Known.getBitWidth(), ~(~
Op->getConstantOperandVal(0) << ShiftAmt)));
3033 case AArch64ISD::MOVIedit: {
3035 Known.getBitWidth(),
3039 case AArch64ISD::MVNIshift: {
3042 ~(
Op->getConstantOperandVal(0) <<
Op->getConstantOperandVal(1)),
3046 case AArch64ISD::MVNImsl: {
3049 APInt(
Known.getBitWidth(), (~
Op->getConstantOperandVal(0) << ShiftAmt),
3053 case AArch64ISD::LOADgot:
3054 case AArch64ISD::ADDlow: {
3055 if (!Subtarget->isTargetILP32())
3061 case AArch64ISD::ASSERT_ZEXT_BOOL: {
3071 case Intrinsic::aarch64_ldaxr:
3072 case Intrinsic::aarch64_ldxr: {
3082 case AArch64ISD::SHL_PRED:
3083 case AArch64ISD::SRL_PRED:
3084 case AArch64ISD::SRA_PRED: {
3094 if (
Op.getOpcode() == AArch64ISD::SHL_PRED)
3096 else if (
Op.getOpcode() == AArch64ISD::SRL_PRED)
3104 unsigned IntNo =
Op.getConstantOperandVal(0);
3108 case Intrinsic::aarch64_neon_uaddlv: {
3109 MVT VT =
Op.getOperand(1).getValueType().getSimpleVT();
3111 if (VT == MVT::v8i8 || VT == MVT::v16i8) {
3112 unsigned Bound = (VT == MVT::v8i8) ? 11 : 12;
3119 case Intrinsic::aarch64_neon_umaxv:
3120 case Intrinsic::aarch64_neon_uminv: {
3125 MVT VT =
Op.getOperand(1).getValueType().getSimpleVT();
3127 if (VT == MVT::v8i8 || VT == MVT::v16i8) {
3131 }
else if (VT == MVT::v4i16 || VT == MVT::v8i16) {
3145 unsigned Depth)
const {
3146 EVT VT =
Op.getValueType();
3148 unsigned Opcode =
Op.getOpcode();
3150 case AArch64ISD::FCMEQ:
3151 case AArch64ISD::FCMGE:
3152 case AArch64ISD::FCMGT:
3155 case AArch64ISD::VASHR: {
3158 return std::min<uint64_t>(Tmp +
Op.getConstantOperandVal(1), VTBits);
3172 switch (
MI->getOpcode()) {
3173 case AArch64::G_FCMEQ:
3174 case AArch64::G_FCMGE:
3175 case AArch64::G_FCMGT: {
3179 case AArch64::G_VASHR: {
3180 unsigned Tmp =
Analysis.computeNumSignBits(
MI->getOperand(1).getReg(),
3181 DemandedElts,
Depth + 1);
3183 return std::min<uint64_t>(Tmp +
MI->getOperand(2).getImm(),
3198 unsigned *
Fast)
const {
3210 bool UseNEONLd1 = Subtarget->requiresStrictAlign() &&
3215 if (ElementSizeBits % 8 == 0 && Alignment >=
Align(ElementSizeBits / 8))
3219 if (Subtarget->requiresStrictAlign())
3224 *
Fast = !Subtarget->isMisaligned128StoreSlow() || VT.
getStoreSize() != 16 ||
3243 unsigned *
Fast)
const {
3244 if (Subtarget->requiresStrictAlign())
3249 *
Fast = !Subtarget->isMisaligned128StoreSlow() ||
3250 Ty.getSizeInBytes() != 16 ||
3293 Register DestReg =
MI.getOperand(0).getReg();
3294 Register IfTrueReg =
MI.getOperand(1).getReg();
3295 Register IfFalseReg =
MI.getOperand(2).getReg();
3296 unsigned CondCode =
MI.getOperand(3).getImm();
3297 bool NZCVKilled =
MI.getOperand(4).isKill();
3311 MBB->addSuccessor(TrueBB);
3312 MBB->addSuccessor(EndBB);
3328 MI.eraseFromParent();
3336 "SEH does not use catchret!");
3350 .
add(
MI.getOperand(0))
3352 MI.eraseFromParent();
3356 Register NewFpmrVal =
MI.getOperand(0).getReg();
3360 MF->
insert(++
MBB->getIterator(), MsrBB);
3379 MBB->addSuccessor(MsrBB);
3382 MI.eraseFromParent();
3393 Register TargetReg =
MI.getOperand(0).getReg();
3395 TII.probedStackAlloc(
MBBI, TargetReg,
false);
3397 MI.eraseFromParent();
3398 return NextInst->getParent();
3451 MBB->addSuccessor(TrapBB);
3452 MBB->addSuccessor(PassBB);
3454 MI.eraseFromParent();
3466 MIB.
add(
MI.getOperand(1));
3467 MIB.
add(
MI.getOperand(2));
3468 MIB.
add(
MI.getOperand(3));
3469 MIB.
add(
MI.getOperand(4));
3470 MIB.
add(
MI.getOperand(5));
3472 MI.eraseFromParent();
3483 MIB.
add(
MI.getOperand(0));
3484 MIB.
add(
MI.getOperand(1));
3485 MIB.
add(
MI.getOperand(2));
3486 MIB.
add(
MI.getOperand(1));
3488 MI.eraseFromParent();
3495 bool Op0IsDef)
const {
3501 for (
unsigned I = 1;
I <
MI.getNumOperands(); ++
I)
3502 MIB.
add(
MI.getOperand(
I));
3504 MI.eraseFromParent();
3514 unsigned StartIdx = 0;
3516 bool HasTile = BaseReg != AArch64::ZA;
3517 bool HasZPROut = HasTile &&
MI.getOperand(0).isReg();
3519 MIB.
add(
MI.getOperand(StartIdx));
3523 MIB.
addReg(BaseReg +
MI.getOperand(StartIdx).getImm(),
3525 MIB.
addReg(BaseReg +
MI.getOperand(StartIdx).getImm());
3529 if (
MI.getOperand(0).isReg() && !
MI.getOperand(1).isImm()) {
3530 MIB.
add(
MI.getOperand(StartIdx));
3535 for (
unsigned I = StartIdx;
I <
MI.getNumOperands(); ++
I)
3536 MIB.
add(
MI.getOperand(
I));
3538 MI.eraseFromParent();
3547 MIB.
add(
MI.getOperand(0));
3549 unsigned Mask =
MI.getOperand(0).getImm();
3550 for (
unsigned I = 0;
I < 8;
I++) {
3551 if (Mask & (1 <<
I))
3555 MI.eraseFromParent();
3565 Register ResultReg =
MI.getOperand(0).getReg();
3568 }
else if (Subtarget->hasSME()) {
3570 .
addImm(AArch64SysReg::SVCR)
3573 RTLIB::Libcall LC = RTLIB::SMEABI_SME_STATE;
3582 MI.eraseFromParent();
3590 while (
Reg.isVirtual()) {
3592 assert(
DefMI &&
"Virtual register definition not found");
3593 unsigned Opcode =
DefMI->getOpcode();
3595 if (Opcode == AArch64::COPY) {
3596 Reg =
DefMI->getOperand(1).getReg();
3598 if (
Reg.isPhysical())
3602 if (Opcode == AArch64::SUBREG_TO_REG) {
3603 Reg =
DefMI->getOperand(1).getReg();
3620 int64_t IntDisc = IntDiscOp.
getImm();
3621 assert(IntDisc == 0 &&
"Blend components are already expanded");
3626 case AArch64::MOVKXi:
3635 case AArch64::MOVi32imm:
3636 case AArch64::MOVi64imm:
3640 AddrDisc = AArch64::NoRegister;
3649 if (AddrDisc == AArch64::XZR)
3650 AddrDisc = AArch64::NoRegister;
3653 if (AddrDisc && MRI.
getRegClass(AddrDisc) != AddrDiscRC) {
3659 if (AddrDiscOp.
getReg() != AddrDisc)
3662 AddrDiscOp.
setReg(AddrDisc);
3663 IntDiscOp.
setImm(IntDisc);
3670 if (SMEOrigInstr != -1) {
3672 uint64_t SMEMatrixType =
3674 switch (SMEMatrixType) {
3690 switch (
MI.getOpcode()) {
3696 case AArch64::EntryPStateSM:
3698 case AArch64::F128CSEL:
3700 case TargetOpcode::STATEPOINT:
3706 MI.addOperand(*
MI.getMF(),
3712 case TargetOpcode::STACKMAP:
3713 case TargetOpcode::PATCHPOINT:
3716 case TargetOpcode::PATCHABLE_EVENT_CALL:
3717 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3720 case AArch64::CATCHRET:
3723 case AArch64::PROBED_STACKALLOC_DYN:
3726 case AArch64::CHECK_MATCHING_VL_PSEUDO:
3729 case AArch64::LD1_MXIPXX_H_PSEUDO_B:
3730 return EmitTileLoad(AArch64::LD1_MXIPXX_H_B, AArch64::ZAB0,
MI, BB);
3731 case AArch64::LD1_MXIPXX_H_PSEUDO_H:
3732 return EmitTileLoad(AArch64::LD1_MXIPXX_H_H, AArch64::ZAH0,
MI, BB);
3733 case AArch64::LD1_MXIPXX_H_PSEUDO_S:
3734 return EmitTileLoad(AArch64::LD1_MXIPXX_H_S, AArch64::ZAS0,
MI, BB);
3735 case AArch64::LD1_MXIPXX_H_PSEUDO_D:
3736 return EmitTileLoad(AArch64::LD1_MXIPXX_H_D, AArch64::ZAD0,
MI, BB);
3737 case AArch64::LD1_MXIPXX_H_PSEUDO_Q:
3738 return EmitTileLoad(AArch64::LD1_MXIPXX_H_Q, AArch64::ZAQ0,
MI, BB);
3739 case AArch64::LD1_MXIPXX_V_PSEUDO_B:
3740 return EmitTileLoad(AArch64::LD1_MXIPXX_V_B, AArch64::ZAB0,
MI, BB);
3741 case AArch64::LD1_MXIPXX_V_PSEUDO_H:
3742 return EmitTileLoad(AArch64::LD1_MXIPXX_V_H, AArch64::ZAH0,
MI, BB);
3743 case AArch64::LD1_MXIPXX_V_PSEUDO_S:
3744 return EmitTileLoad(AArch64::LD1_MXIPXX_V_S, AArch64::ZAS0,
MI, BB);
3745 case AArch64::LD1_MXIPXX_V_PSEUDO_D:
3746 return EmitTileLoad(AArch64::LD1_MXIPXX_V_D, AArch64::ZAD0,
MI, BB);
3747 case AArch64::LD1_MXIPXX_V_PSEUDO_Q:
3748 return EmitTileLoad(AArch64::LD1_MXIPXX_V_Q, AArch64::ZAQ0,
MI, BB);
3749 case AArch64::LDR_ZA_PSEUDO:
3751 case AArch64::LDR_TX_PSEUDO:
3753 case AArch64::STR_TX_PSEUDO:
3755 case AArch64::ZERO_M_PSEUDO:
3757 case AArch64::ZERO_T_PSEUDO:
3759 case AArch64::MOVT_TIZ_PSEUDO:
3761 case AArch64::MSR_FPMR:
3766 &AArch64::GPR64noipRegClass);
3796 N =
N->getOperand(0).getNode();
3801 if (
N->getOpcode() != AArch64ISD::DUP)
3804 auto Opnd0 =
N->getOperand(0);
3810 (V.getOpcode() == AArch64ISD::DUP &&
isOneConstant(V.getOperand(0)));
3971 CondCode, CondCode2);
3991 if (
Op->getFlags().hasNoSignedWrap())
4017 (isIntEqualitySetCC(CC) ||
4025 EVT VT =
LHS.getValueType();
4030 if ((VT == MVT::f16 && !FullFP16) || VT == MVT::bf16) {
4035 Chain =
RHS.getValue(1);
4038 IsSignaling ? AArch64ISD::STRICT_FCMPE : AArch64ISD::STRICT_FCMP;
4044 EVT VT =
LHS.getValueType();
4049 if ((VT == MVT::f16 && !FullFP16) || VT == MVT::bf16) {
4060 unsigned Opcode = AArch64ISD::SUBS;
4064 Opcode = AArch64ISD::ADDS;
4067 isIntEqualitySetCC(CC)) {
4070 Opcode = AArch64ISD::ADDS;
4079 LHS.getOperand(0),
LHS.getOperand(1));
4083 }
else if (
LHS.getOpcode() == AArch64ISD::ANDS) {
4085 return LHS.getValue(1);
4151 unsigned Opcode = 0;
4154 if (
LHS.getValueType().isFloatingPoint()) {
4155 assert(
LHS.getValueType() != MVT::f128);
4156 if ((
LHS.getValueType() == MVT::f16 && !FullFP16) ||
4157 LHS.getValueType() == MVT::bf16) {
4161 Opcode = AArch64ISD::FCCMP;
4163 APInt Imm = Const->getAPIntValue();
4164 if (
Imm.isNegative() &&
Imm.sgt(-32)) {
4165 Opcode = AArch64ISD::CCMN;
4169 Opcode = AArch64ISD::CCMN;
4172 isIntEqualitySetCC(CC)) {
4175 Opcode = AArch64ISD::CCMN;
4179 Opcode = AArch64ISD::CCMP;
4205 bool &CanNegate,
bool &MustBeFirst,
4206 bool &PreferFirst,
bool WillNegate,
4207 unsigned Depth = 0) {
4213 if (VT == MVT::f128)
4216 MustBeFirst =
false;
4220 {Val->getOperand(0), Val->getOperand(1)});
4227 bool IsOR = Opcode ==
ISD::OR;
4243 if (MustBeFirstL && MustBeFirstR)
4249 if (!CanNegateL && !CanNegateR)
4253 CanNegate = WillNegate && CanNegateL && CanNegateR;
4256 MustBeFirst = !CanNegate;
4261 MustBeFirst = MustBeFirstL || MustBeFirstR;
4263 PreferFirst = PreferFirstL || PreferFirstR;
4286 bool isInteger =
LHS.getValueType().isInteger();
4288 CC = getSetCCInverse(CC,
LHS.getValueType());
4294 assert(
LHS.getValueType().isFloatingPoint());
4320 bool IsOR = Opcode ==
ISD::OR;
4327 PreferFirstL, IsOR);
4328 assert(ValidL &&
"Valid conjunction/disjunction tree");
4336 PreferFirstR, IsOR);
4337 assert(ValidR &&
"Valid conjunction/disjunction tree");
4340 bool ShouldFirstL = PreferFirstL && !PreferFirstR && !MustBeFirstR;
4343 if (MustBeFirstL || ShouldFirstL) {
4344 assert(!MustBeFirstR &&
"Valid conjunction/disjunction tree");
4353 bool NegateAfterAll;
4357 assert(CanNegateR &&
"at least one side must be negatable");
4358 assert(!MustBeFirstR &&
"invalid conjunction/disjunction tree");
4362 NegateAfterR =
true;
4365 NegateR = CanNegateR;
4366 NegateAfterR = !CanNegateR;
4369 NegateAfterAll = !Negate;
4371 assert(Opcode ==
ISD::AND &&
"Valid conjunction/disjunction tree");
4372 assert(!Negate &&
"Valid conjunction/disjunction tree");
4376 NegateAfterR =
false;
4377 NegateAfterAll =
false;
4397 bool DummyCanNegate;
4398 bool DummyMustBeFirst;
4399 bool DummyPreferFirst;
4401 DummyPreferFirst,
false))
4415 uint64_t Mask = MaskCst->getZExtValue();
4416 return (Mask == 0xFF || Mask == 0xFFFF || Mask == 0xFFFFFFFF);
4424 if (!
Op.hasOneUse())
4430 unsigned Opc =
Op.getOpcode();
4433 uint64_t Shift = ShiftCst->getZExtValue();
4435 return (Shift <= 4) ? 2 : 1;
4436 EVT VT =
Op.getValueType();
4437 if ((VT == MVT::i32 && Shift <= 31) || (VT == MVT::i64 && Shift <= 63))
4457 if (
LHS.getOpcode() !=
ISD::AND &&
LHS.getOpcode() != AArch64ISD::ANDS)
4477 EVT VT =
RHS.getValueType();
4478 APInt C = RHSC->getAPIntValue();
4493 if (!
C.isMinSignedValue()) {
4505 assert(!
C.isZero() &&
"C should not be zero here");
4516 if (!
C.isMaxSignedValue()) {
4527 if (!
C.isAllOnes()) {
4587 LHS->hasNUsesOfValue(1, 0)) {
4588 int16_t ValueofRHS =
RHS->getAsZExtVal();
4616static std::pair<SDValue, SDValue>
4618 assert((
Op.getValueType() == MVT::i32 ||
Op.getValueType() == MVT::i64) &&
4619 "Unsupported value type");
4625 switch (
Op.getOpcode()) {
4629 Opc = AArch64ISD::ADDS;
4633 Opc = AArch64ISD::ADDS;
4637 Opc = AArch64ISD::SUBS;
4641 Opc = AArch64ISD::SUBS;
4649 if (
Op.getValueType() == MVT::i32) {
4672 assert(
Op.getValueType() == MVT::i64 &&
"Expected an i64 value type");
4682 Overflow = DAG.
getNode(AArch64ISD::SUBS,
DL, VTs, UpperBits, LowerBits)
4701 Overflow =
Value.getValue(1);
4703 return std::make_pair(
Value, Overflow);
4708 !Subtarget->isNeonAvailable()))
4709 return LowerToScalableOp(
Op, DAG);
4733 return DAG.
getNode(AArch64ISD::CSEL,
DL,
Op.getValueType(), TVal, FVal,
4756 if (
LHS.getValueType() != MVT::i32 &&
LHS.getValueType() != MVT::i64)
4763 if (!CFVal || !CTVal)
4800 return Cmp.getValue(1);
4813 return DAG.
getNode(AArch64ISD::CSEL,
DL, VT, One, Zero, CC, Glue);
4823 return DAG.
getNode(AArch64ISD::CSEL,
DL, VT, One, Zero, CC, Glue);
4829 unsigned Opcode,
bool IsSigned) {
4830 EVT VT0 =
Op.getValue(0).getValueType();
4831 EVT VT1 =
Op.getValue(1).getValueType();
4833 if (VT0 != MVT::i32 && VT0 != MVT::i64)
4836 bool InvertCarry = Opcode == AArch64ISD::SBCS;
4855 bool LastOperandIsImm =
false) {
4856 if (
Op.getValueType().isVector())
4861 const unsigned NumOperands =
Op.getNumOperands();
4862 auto getFloatVT = [](
EVT VT) {
4863 assert((VT == MVT::i32 || VT == MVT::i64) &&
"Unexpected VT");
4864 return VT == MVT::i32 ? MVT::f32 : MVT::f64;
4866 auto bitcastToFloat = [&](
SDValue Val) {
4867 return DAG.
getBitcast(getFloatVT(Val.getValueType()), Val);
4871 for (
unsigned I = 1;
I < NumOperands; ++
I) {
4873 const bool KeepInt = LastOperandIsImm && (
I == NumOperands - 1);
4874 NewOps.
push_back(KeepInt ? Val : bitcastToFloat(Val));
4876 EVT OrigVT =
Op.getValueType();
4901 DAG.
getNode(AArch64ISD::CSEL,
DL, MVT::i32, FVal, TVal, CCVal, Overflow);
4913 unsigned IsWrite =
Op.getConstantOperandVal(2);
4914 unsigned Locality =
Op.getConstantOperandVal(3);
4915 unsigned IsData =
Op.getConstantOperandVal(4);
4917 bool IsStream = !Locality;
4921 assert(Locality <= 3 &&
"Prefetch locality out-of-range");
4925 Locality = 3 - Locality;
4929 unsigned PrfOp = (IsWrite << 4) |
4933 return DAG.
getNode(AArch64ISD::PREFETCH,
DL, MVT::Other,
Op.getOperand(0),
4946 if (LHSConstOp && RHSConst) {
4950 uint64_t NewMaskValue = LHSConstValue & ~(RHSConstant - 1);
4963 EVT VT =
Op.getValueType();
4967 if (VT == MVT::nxv2f64 && SrcVal.
getValueType() == MVT::nxv2bf16) {
4975 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FP_EXTEND_MERGE_PASSTHRU);
4979 return LowerFixedLengthFPExtendToSVE(
Op, DAG);
4981 bool IsStrict =
Op->isStrictFPOpcode();
4982 SDValue Op0 =
Op.getOperand(IsStrict ? 1 : 0);
4984 if (VT == MVT::f64) {
4986 if (Op0VT == MVT::f32 || Op0VT == MVT::f16)
4989 if (Op0VT == MVT::bf16 && IsStrict) {
4992 {
Op.getOperand(0), Op0});
4996 if (Op0VT == MVT::bf16)
5002 assert(
Op.getValueType() == MVT::f128 &&
"Unexpected lowering");
5008 EVT VT =
Op.getValueType();
5009 bool IsStrict =
Op->isStrictFPOpcode();
5010 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5012 bool Trunc =
Op.getConstantOperandVal(IsStrict ? 2 : 1) == 1;
5013 SDNodeFlags
Flags =
Op->getFlags();
5017 if (SrcVT == MVT::nxv8f32)
5021 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FP_ROUND_MERGE_PASSTHRU);
5024 constexpr EVT
I32 = MVT::nxv4i32;
5030 if (SrcVT == MVT::nxv2f32 || SrcVT == MVT::nxv4f32) {
5031 if (Subtarget->hasBF16())
5032 return LowerToPredicatedOp(
Op, DAG,
5033 AArch64ISD::FP_ROUND_MERGE_PASSTHRU);
5035 Narrow = getSVESafeBitCast(I32, SrcVal, DAG);
5040 }
else if (SrcVT == MVT::nxv2f64 &&
5041 (Subtarget->hasSVE2() || Subtarget->isStreamingSVEAvailable())) {
5044 Narrow = DAG.
getNode(AArch64ISD::FCVTX_MERGE_PASSTHRU,
DL, MVT::nxv2f32,
5045 Pg, SrcVal, DAG.
getPOISON(MVT::nxv2f32));
5051 NewOps.
push_back(
Op.getOperand(IsStrict ? 2 : 1));
5052 return DAG.
getNode(
Op.getOpcode(),
DL, VT, NewOps,
Op->getFlags());
5069 IsNaN = DAG.
getNode(AArch64ISD::REINTERPRET_CAST,
DL, I1, IsNaN);
5070 Narrow = DAG.
getSelect(
DL, I32, IsNaN, NaN, Narrow);
5075 return getSVESafeBitCast(VT, Narrow, DAG);
5079 return LowerFixedLengthFPRoundToSVE(
Op, DAG);
5084 !((Subtarget->hasNEON() || Subtarget->hasSME()) &&
5085 Subtarget->hasBF16())) {
5100 Narrow = DAG.
getNode(AArch64ISD::FCVTXN,
DL,
F32, Narrow);
5121 Narrow = DAG.
getSelect(
DL, I32, IsNaN, NaN, Narrow);
5138 if (SrcVT != MVT::f128) {
5155 bool IsStrict =
Op->isStrictFPOpcode();
5156 EVT InVT =
Op.getOperand(IsStrict ? 1 : 0).getValueType();
5157 EVT VT =
Op.getValueType();
5160 "Unimplemented SVE support for STRICT_FP_to_INT!");
5169 {
Op.getOperand(0),
Op.getOperand(1)});
5170 return DAG.
getNode(
Op.getOpcode(),
DL, {VT, MVT::Other},
5171 {Ext.getValue(1), Ext.getValue(0)});
5174 Op.getOpcode(),
DL,
Op.getValueType(),
5178 if (
SDValue Res = LowerFPToIntToSVE(
Op, DAG))
5183 if (VTSize < InVTSize) {
5188 {Op.getOperand(0), Op.getOperand(1)});
5198 if (VTSize > InVTSize) {
5205 {
Op.getOperand(0),
Op.getOperand(1)});
5206 return DAG.
getNode(
Op.getOpcode(),
DL, {VT, MVT::Other},
5207 {Ext.getValue(1), Ext.getValue(0)});
5222 return DAG.
getNode(
Op.getOpcode(),
DL, {ScalarVT, MVT::Other},
5223 {Op.getOperand(0), Extract});
5224 return DAG.
getNode(
Op.getOpcode(),
DL, ScalarVT, Extract);
5233 bool IsStrict =
Op->isStrictFPOpcode();
5234 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5237 return LowerVectorFP_TO_INT(
Op, DAG);
5240 if ((SrcVal.
getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) ||
5246 {
Op.getOperand(0), SrcVal});
5247 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
5248 {Ext.getValue(1), Ext.getValue(0)});
5263AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(
SDValue Op,
5269 const EVT DstVT =
Op.getValueType();
5276 assert(SatWidth <= DstElementWidth &&
5277 "Saturation width cannot exceed result width");
5280 if (SrcElementVT != MVT::f64 && SrcElementVT != MVT::f32 &&
5281 SrcElementVT != MVT::f16 && SrcElementVT != MVT::bf16)
5284 if (
SDValue Res = LowerFPToIntToSVE(
Op, DAG))
5288 auto CanHandleNatively = [&DstVT, &SatWidth](EVT SrcVT) ->
bool {
5294 auto Expand = [&SatWidth, &CanHandleNatively](EVT SrcVT) ->
bool {
5295 return !CanHandleNatively(SrcVT) &&
5299 (SrcVT == MVT::v1f64 || SrcVT == MVT::v2f64));
5304 std::optional<EVT> PromVT;
5308 if (DstElementVT == MVT::i32 || SrcElementVT == MVT::bf16 ||
5309 !Subtarget->hasFullFP16()) {
5316 if (DstElementVT == MVT::i64) {
5326 unsigned Opc =
Op.getOpcode();
5327 if (PromVT && !
Expand(*PromVT)) {
5330 if (*PromVT != MVT::v8f32 ||
isTypeLegal(MVT::v8f32))
5331 return DAG.
getNode(
Op.getOpcode(),
DL, DstVT, SrcVal,
Op.getOperand(1));
5345 if (CanHandleNatively(SrcVT)) {
5349 }
else if (
Expand(SrcVT)) {
5353 assert((SrcElementWidth > DstElementWidth) ||
5354 (SrcElementWidth == DstElementWidth && SatWidth < DstElementWidth));
5384 return LowerVectorFP_TO_INT_SAT(
Op, DAG);
5386 EVT DstVT =
Op.getValueType();
5390 assert(SatWidth <= DstWidth &&
"Saturation width cannot exceed result width");
5393 if ((SrcVT == MVT::f16 && !Subtarget->hasFullFP16()) || SrcVT == MVT::bf16) {
5396 }
else if (SrcVT != MVT::f64 && SrcVT != MVT::f32 && SrcVT != MVT::f16 &&
5402 if ((SrcVT == MVT::f64 || SrcVT == MVT::f32 ||
5403 (SrcVT == MVT::f16 && Subtarget->hasFullFP16())) &&
5404 DstVT == SatVT && (DstVT == MVT::i64 || DstVT == MVT::i32))
5405 return DAG.
getNode(
Op.getOpcode(),
DL, DstVT, SrcVal,
5411 if (DstWidth < SatWidth)
5414 if (SrcVT == MVT::f16 && SatVT == MVT::i16 && DstVT == MVT::i32) {
5417 DAG.
getNode(AArch64ISD::FCVTZS_HALF,
DL, MVT::f32, SrcVal);
5422 SDValue CVTf32 = DAG.
getNode(AArch64ISD::FCVTZU_HALF,
DL, MVT::f32, SrcVal);
5447 EVT VT =
Op.getValueType();
5454 *DAG.
getContext(), Src.getValueType().getVectorElementType());
5470 bool IsStrict =
Op->isStrictFPOpcode();
5471 EVT VT =
Op.getValueType();
5474 EVT InVT =
In.getValueType();
5475 unsigned Opc =
Op.getOpcode();
5479 "Unimplemented SVE support for ISD:::STRICT_INT_TO_FP!");
5494 {Op.getOperand(0), In});
5496 {
Op.getValueType(), MVT::Other},
5507 if (VT == MVT::nxv8f32)
5510 unsigned Opcode = IsSigned ? AArch64ISD::SINT_TO_FP_MERGE_PASSTHRU
5511 : AArch64ISD::UINT_TO_FP_MERGE_PASSTHRU;
5512 return LowerToPredicatedOp(
Op, DAG, Opcode);
5517 return LowerFixedLengthIntToFPToSVE(
Op, DAG);
5521 if (VTSize < InVTSize) {
5527 bool IsTargetf16 =
false;
5528 if (
Op.hasOneUse() &&
5533 SDNode *
U = *
Op->user_begin();
5534 if (
U->hasOneUse() &&
U->user_begin()->getOpcode() ==
ISD::FP_ROUND) {
5535 EVT TmpVT =
U->user_begin()->getValueType(0);
5541 if (IsTargetf32 && !IsTargetf16) {
5551 {
In.getValue(1),
In.getValue(0),
5559 if (VTSize > InVTSize) {
5576 return DAG.
getNode(
Op.getOpcode(),
DL, {ScalarVT, MVT::Other},
5577 {Op.getOperand(0), Extract});
5578 return DAG.
getNode(
Op.getOpcode(),
DL, ScalarVT, Extract);
5586 if (
Op.getValueType().isVector())
5587 return LowerVectorINT_TO_FP(
Op, DAG);
5589 bool IsStrict =
Op->isStrictFPOpcode();
5590 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5595 auto IntToFpViaPromotion = [&](EVT PromoteVT) {
5599 {Op.getOperand(0), SrcVal});
5601 {
Op.getValueType(), MVT::Other},
5606 DAG.
getNode(
Op.getOpcode(),
DL, PromoteVT, SrcVal),
5610 if (
Op.getValueType() == MVT::bf16) {
5611 unsigned MaxWidth = IsSigned
5615 if (MaxWidth <= 24) {
5616 return IntToFpViaPromotion(MVT::f32);
5620 if (MaxWidth <= 53) {
5621 return IntToFpViaPromotion(MVT::f64);
5672 IsStrict ? DAG.
getNode(
Op.getOpcode(),
DL, {MVT::f64, MVT::Other},
5673 {Op.getOperand(0), ToRound})
5674 : DAG.
getNode(
Op.getOpcode(),
DL, MVT::f64, ToRound);
5701 {
Op.getValueType(), MVT::Other},
5705 DAG.getIntPtrConstant(0,
DL,
true));
5710 if (
Op.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) {
5711 return IntToFpViaPromotion(MVT::f32);
5720 if (
Op.getValueType() != MVT::f128)
5728AArch64TargetLowering::LowerLOOP_DEPENDENCE_MASK(
SDValue Op,
5730 assert((Subtarget->hasSVE2() ||
5731 (Subtarget->hasSME() && Subtarget->isStreaming())) &&
5732 "Lowering loop_dependence_raw_mask or loop_dependence_war_mask "
5733 "requires SVE or SME");
5736 EVT VT =
Op.getValueType();
5737 unsigned LaneOffset =
Op.getConstantOperandVal(3);
5739 uint64_t EltSizeInBytes =
Op.getConstantOperandVal(2);
5740 EVT AddrTy =
Op->getOperand(0).getValueType();
5743 if (LaneOffset != 0 || !
is_contained({1u, 2u, 4u, 8u}, EltSizeInBytes))
5752 if (AddrTy == MVT::i64)
5756 assert(AddrTy == MVT::i32 &&
"Only expected i32 to be legal!");
5758 Op.getOpcode(),
DL, VT,
5783 EVT OpVT =
Op.getValueType();
5784 EVT ArgVT =
Op.getOperand(0).getValueType();
5787 return LowerFixedLengthBitcastToSVE(
Op, DAG);
5795 "Expected int->fp bitcast!");
5808 return getSVESafeBitCast(OpVT, ExtResult, DAG);
5819 return getSVESafeBitCast(OpVT,
Op.getOperand(0), DAG);
5822 if (OpVT != MVT::f16 && OpVT != MVT::bf16)
5826 if (ArgVT == MVT::f16 || ArgVT == MVT::bf16)
5836 assert(ArgVT == MVT::i16);
5841 Src.getOperand(0).getValueType().changeElementType(
5857static std::optional<uint64_t>
5861 return std::nullopt;
5866 return std::nullopt;
5868 return C->getZExtValue();
5873 EVT VT =
N.getValueType();
5878 for (
const SDValue &Elt :
N->op_values()) {
5881 unsigned HalfSize = EltSize / 2;
5883 if (!
isIntN(HalfSize,
C->getSExtValue()))
5886 if (!
isUIntN(HalfSize,
C->getZExtValue()))
5898 EVT VT =
N.getValueType();
5920 unsigned Opcode =
N.getOpcode();
5931 unsigned Opcode =
N.getOpcode();
6073 if (IsN0SExt && IsN1SExt)
6074 return AArch64ISD::SMULL;
6079 if (IsN0ZExt && IsN1ZExt)
6080 return AArch64ISD::UMULL;
6086 if (IsN0ZExt || IsN1ZExt) {
6088 return AArch64ISD::UMULL;
6093 return AArch64ISD::UMULL;
6096 if (IsN0SExt || IsN1SExt) {
6098 return AArch64ISD::SMULL;
6101 return AArch64ISD::SMULL;
6104 if (!IsN1SExt && !IsN1ZExt)
6111 return AArch64ISD::SMULL;
6115 return AArch64ISD::UMULL;
6120 return AArch64ISD::UMULL;
6141 const SDNode *Operand =
N->getOperand(1).getNode();
6150 SplatValue = SplatValue.
abs();
6159 if ((SplatValue - 1).isPowerOf2())
6161 else if ((SplatValue + 1).isPowerOf2())
6170 EVT VT =
N->getValueType(0);
6173 unsigned ShiftAmt = MathOp ==
ISD::ADD ? (SplatValue - 1).logBase2()
6174 : (SplatValue + 1).logBase2();
6192 EVT VT =
Op.getValueType();
6194 bool OverrideNEON = !Subtarget->isNeonAvailable();
6196 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::MUL_PRED);
6201 "unexpected type for custom-lowering ISD::MUL");
6217 if (VT == MVT::v1i64) {
6218 if (Subtarget->hasSVE())
6219 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::MUL_PRED);
6235 if (Subtarget->hasSVE())
6236 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::MUL_PRED);
6254 "unexpected types for extended operands to VMULL");
6256 DAG.
getNode(NewOpc,
DL, VT, Op0, Op1), 0);
6276 if (
Pattern == AArch64SVEPredPattern::all)
6285 if (PatNumElts == (NumElts * VScale))
6289 return DAG.
getNode(AArch64ISD::PTRUE,
DL, VT,
6300 IID = Intrinsic::aarch64_sve_ptrue_c8;
6303 IID = Intrinsic::aarch64_sve_ptrue_c16;
6306 IID = Intrinsic::aarch64_sve_ptrue_c32;
6309 IID = Intrinsic::aarch64_sve_ptrue_c64;
6318 bool IsSigned,
bool IsEqual) {
6322 if (!
N->getValueType(0).isScalableVector() ||
6327 APInt Y =
N->getConstantOperandAPInt(Op1);
6332 if (IsSigned ?
Y.isMaxSignedValue() :
Y.isMaxValue())
6338 APInt X =
N->getConstantOperandAPInt(Op0);
6341 APInt NumActiveElems =
6342 IsSigned ?
Y.ssub_ov(
X, Overflow) :
Y.usub_ov(
X, Overflow);
6349 NumActiveElems = IsSigned ? NumActiveElems.
sadd_ov(One, Overflow)
6350 : NumActiveElems.
uadd_ov(One, Overflow);
6355 std::optional<unsigned> PredPattern =
6357 unsigned MinSVEVectorSize = std::max(
6359 unsigned ElementSize = 128 /
N->getValueType(0).getVectorMinNumElements();
6360 if (PredPattern != std::nullopt &&
6361 NumActiveElems.
getZExtValue() <= (MinSVEVectorSize / ElementSize))
6362 return getPTrue(DAG,
DL,
N->getValueType(0), *PredPattern);
6371 EVT VT =
N->getValueType(0);
6379 unsigned BrkID = Intrinsic::aarch64_sve_brkb_z;
6382 BrkID = Intrinsic::aarch64_sve_brka_z;
6389 Upper.getOperand(0).getValueType() != VT)
6398 DAG.
getNode(AArch64ISD::REINTERPRET_CAST,
DL, MVT::nxv16i1, Mask);
6402 return DAG.
getNode(AArch64ISD::REINTERPRET_CAST,
DL, VT, Brk);
6409 EVT InVT =
Op.getValueType();
6413 "Expected a predicate-to-predicate bitcast");
6417 "Only expect to cast between legal scalable predicate types!");
6427 Op.getConstantOperandVal(0) == Intrinsic::aarch64_sve_convert_to_svbool &&
6428 Op.getOperand(1).getValueType().bitsGT(VT))
6429 Op =
Op.getOperand(1);
6447 Mask = DAG.
getNode(AArch64ISD::REINTERPRET_CAST,
DL, VT, Mask);
6454 RTLIB::Libcall LC = RTLIB::SMEABI_SME_STATE;
6460 TargetLowering::CallLoweringInfo CLI(DAG);
6462 CLI.setDebugLoc(
DL).setChain(Chain).setLibCallee(
6465 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
6511 SDValue TileSlice =
N->getOperand(2);
6514 int32_t ConstAddend = 0;
6523 ConstAddend = ImmNode->getSExtValue();
6527 int32_t ImmAddend = ConstAddend % 16;
6528 if (int32_t
C = (ConstAddend - ImmAddend)) {
6530 VarAddend = VarAddend
6537 auto SVL = DAG.
getNode(AArch64ISD::RDSVL,
DL, MVT::i64,
6549 return DAG.
getNode(IsLoad ? AArch64ISD::SME_ZA_LDR : AArch64ISD::SME_ZA_STR,
6551 {
N.getOperand(0), TileSlice,
Base,
6557 auto Op1 =
Op.getOperand(0);
6558 auto Op2 =
Op.getOperand(1);
6559 auto Mask =
Op.getOperand(2);
6562 EVT Op2VT = Op2.getValueType();
6563 EVT ResVT =
Op.getValueType();
6565 if ((Op2VT == MVT::v3i8 || Op2VT == MVT::v4i8)) {
6567 EVT NeedleVT = Op2VT;
6569 if (NeedleVT == MVT::v3i8) {
6619 Op2 = DAG.
getNode(AArch64ISD::DUPLANE128,
DL, OpContainerVT, Op2,
6650 ID, Mask, Op1, Op2);
6661 unsigned IntNo =
Op.getConstantOperandVal(1);
6666 case Intrinsic::aarch64_prefetch: {
6670 unsigned IsWrite =
Op.getConstantOperandVal(3);
6671 unsigned Locality =
Op.getConstantOperandVal(4);
6672 unsigned IsStream =
Op.getConstantOperandVal(5);
6673 unsigned IsData =
Op.getConstantOperandVal(6);
6674 unsigned PrfOp = (IsWrite << 4) |
6679 return DAG.
getNode(AArch64ISD::PREFETCH,
DL, MVT::Other, Chain,
6682 case Intrinsic::aarch64_range_prefetch: {
6686 unsigned IsWrite =
Op.getConstantOperandVal(3);
6687 unsigned IsStream =
Op.getConstantOperandVal(4);
6688 unsigned PrfOp = (IsStream << 2) | IsWrite;
6691 return DAG.
getNode(AArch64ISD::RANGE_PREFETCH,
DL, MVT::Other, Chain,
6695 case Intrinsic::aarch64_prefetch_ir:
6696 return DAG.
getNode(AArch64ISD::PREFETCH,
DL, MVT::Other,
6700 case Intrinsic::aarch64_sme_str:
6701 case Intrinsic::aarch64_sme_ldr: {
6704 case Intrinsic::aarch64_sme_za_enable:
6706 AArch64ISD::SMSTART,
DL, DAG.
getVTList(MVT::Other, MVT::Glue),
6709 case Intrinsic::aarch64_sme_za_disable:
6711 AArch64ISD::SMSTOP,
DL, DAG.
getVTList(MVT::Other, MVT::Glue),
6719 unsigned IntNo =
Op.getConstantOperandVal(1);
6724 case Intrinsic::aarch64_svc:
6725 case Intrinsic::aarch64_hvc: {
6732 unsigned Imm =
Op.getConstantOperandVal(2);
6739 for (
unsigned I = 0;
I < std::size(
ArgGPRs); ++
I) {
6749 Ops.push_back(Chain);
6753 Ops.push_back(Glue);
6756 IntNo == Intrinsic::aarch64_svc ? AArch64ISD::SVC : AArch64ISD::HVC;
6759 Chain =
Node.getValue(0);
6760 Glue =
Node.getValue(1);
6765 case Intrinsic::aarch64_mops_memset_tag: {
6773 bool IsVol =
Node->isVolatile();
6774 auto DstPtrInfo =
Node->getPointerInfo();
6778 SDValue MS = SDI.EmitMOPS(AArch64::MOPSMemorySetTaggingPseudo, DAG,
DL,
6779 Chain, Dst, Val,
Size, Alignment, Alignment,
6780 IsVol, DstPtrInfo, MachinePointerInfo{});
6793 unsigned IntNo =
Op.getConstantOperandVal(0);
6797 case Intrinsic::thread_pointer: {
6799 return DAG.
getNode(AArch64ISD::THREAD_POINTER,
DL, PtrVT);
6801 case Intrinsic::aarch64_sve_whilewr_b:
6803 Op.getOperand(1),
Op.getOperand(2),
6806 case Intrinsic::aarch64_sve_whilewr_h:
6808 Op.getOperand(1),
Op.getOperand(2),
6811 case Intrinsic::aarch64_sve_whilewr_s:
6813 Op.getOperand(1),
Op.getOperand(2),
6816 case Intrinsic::aarch64_sve_whilewr_d:
6818 Op.getOperand(1),
Op.getOperand(2),
6821 case Intrinsic::aarch64_sve_whilerw_b:
6823 Op.getOperand(1),
Op.getOperand(2),
6826 case Intrinsic::aarch64_sve_whilerw_h:
6828 Op.getOperand(1),
Op.getOperand(2),
6831 case Intrinsic::aarch64_sve_whilerw_s:
6833 Op.getOperand(1),
Op.getOperand(2),
6836 case Intrinsic::aarch64_sve_whilerw_d:
6838 Op.getOperand(1),
Op.getOperand(2),
6841 case Intrinsic::aarch64_neon_abs: {
6842 EVT Ty =
Op.getValueType();
6843 if (Ty == MVT::i64) {
6855 case Intrinsic::aarch64_neon_addhn: {
6856 return DAG.
getNode(AArch64ISD::ADDHN,
DL,
Op.getValueType(),
6857 Op.getOperand(1),
Op.getOperand(2));
6859 case Intrinsic::aarch64_neon_pmull64: {
6863 std::optional<uint64_t> LHSLane =
6865 std::optional<uint64_t> RHSLane =
6868 assert((!LHSLane || *LHSLane < 2) &&
"Expect lane to be None or 0 or 1");
6869 assert((!RHSLane || *RHSLane < 2) &&
"Expect lane to be None or 0 or 1");
6875 auto TryVectorizeOperand = [](
SDValue N, std::optional<uint64_t> NLane,
6876 std::optional<uint64_t> OtherLane,
6878 SelectionDAG &DAG) ->
SDValue {
6886 if (OtherLane == 1) {
6896 DAG.
getNode(AArch64ISD::DUPLANE64,
DL, MVT::v2i64,
6901 return DAG.
getNode(AArch64ISD::DUP,
DL, MVT::v1i64,
N);
6906 assert(
N.getValueType() == MVT::i64 &&
6907 "Intrinsic aarch64_neon_pmull64 requires i64 parameters");
6911 LHS = TryVectorizeOperand(
LHS, LHSLane, RHSLane,
DL, DAG);
6912 RHS = TryVectorizeOperand(
RHS, RHSLane, LHSLane,
DL, DAG);
6916 case Intrinsic::aarch64_neon_smax:
6919 case Intrinsic::aarch64_neon_umax:
6922 case Intrinsic::aarch64_neon_smin:
6925 case Intrinsic::aarch64_neon_umin:
6928 case Intrinsic::aarch64_neon_scalar_sqxtn:
6929 case Intrinsic::aarch64_neon_scalar_sqxtun:
6930 case Intrinsic::aarch64_neon_scalar_uqxtn: {
6931 assert(
Op.getValueType() == MVT::i32 ||
Op.getValueType() == MVT::f32);
6932 if (
Op.getValueType() == MVT::i32)
6937 Op.getOperand(1))));
6940 case Intrinsic::aarch64_neon_sqxtn:
6943 case Intrinsic::aarch64_neon_sqxtun:
6946 case Intrinsic::aarch64_neon_uqxtn:
6949 case Intrinsic::aarch64_neon_sqshrn:
6950 if (
Op.getValueType().isVector())
6953 Op.getOperand(1).getValueType(),
6954 Op.getOperand(1),
Op.getOperand(2)));
6957 case Intrinsic::aarch64_neon_sqshrun:
6958 if (
Op.getValueType().isVector())
6961 Op.getOperand(1).getValueType(),
6962 Op.getOperand(1),
Op.getOperand(2)));
6965 case Intrinsic::aarch64_neon_uqshrn:
6966 if (
Op.getValueType().isVector())
6969 Op.getOperand(1).getValueType(),
6970 Op.getOperand(1),
Op.getOperand(2)));
6973 case Intrinsic::aarch64_neon_sqrshrn:
6974 if (
Op.getValueType().isVector())
6977 Op.getOperand(1).getValueType(),
6978 Op.getOperand(1),
Op.getOperand(2)));
6981 case Intrinsic::aarch64_neon_sqrshrun:
6982 if (
Op.getValueType().isVector())
6985 Op.getOperand(1).getValueType(),
6986 Op.getOperand(1),
Op.getOperand(2)));
6989 case Intrinsic::aarch64_neon_uqrshrn:
6990 if (
Op.getValueType().isVector())
6993 Op.getOperand(1).getValueType(),
6994 Op.getOperand(1),
Op.getOperand(2)));
6997 case Intrinsic::aarch64_neon_sqdmulh:
6999 case Intrinsic::aarch64_neon_sqrdmulh:
7001 case Intrinsic::aarch64_neon_sqrdmlah:
7003 case Intrinsic::aarch64_neon_sqrdmlsh:
7005 case Intrinsic::aarch64_neon_sqrshl:
7007 case Intrinsic::aarch64_neon_sqshl:
7009 case Intrinsic::aarch64_neon_uqrshl:
7011 case Intrinsic::aarch64_neon_uqshl:
7013 case Intrinsic::aarch64_neon_sqadd:
7014 if (
Op.getValueType().isVector())
7019 case Intrinsic::aarch64_neon_sqsub:
7020 if (
Op.getValueType().isVector())
7025 case Intrinsic::aarch64_neon_uqadd:
7026 if (
Op.getValueType().isVector())
7030 case Intrinsic::aarch64_neon_suqadd:
7032 case Intrinsic::aarch64_neon_usqadd:
7034 case Intrinsic::aarch64_neon_uqsub:
7035 if (
Op.getValueType().isVector())
7039 case Intrinsic::aarch64_neon_sqdmulls_scalar:
7041 case Intrinsic::aarch64_neon_sqabs:
7043 case Intrinsic::aarch64_neon_sqneg:
7045 case Intrinsic::aarch64_sve_whilelt:
7048 case Intrinsic::aarch64_sve_whilels:
7051 case Intrinsic::aarch64_sve_whilele:
7054 case Intrinsic::aarch64_sve_sunpkhi:
7055 return DAG.
getNode(AArch64ISD::SUNPKHI,
DL,
Op.getValueType(),
7057 case Intrinsic::aarch64_sve_sunpklo:
7058 return DAG.
getNode(AArch64ISD::SUNPKLO,
DL,
Op.getValueType(),
7060 case Intrinsic::aarch64_sve_uunpkhi:
7061 return DAG.
getNode(AArch64ISD::UUNPKHI,
DL,
Op.getValueType(),
7063 case Intrinsic::aarch64_sve_uunpklo:
7064 return DAG.
getNode(AArch64ISD::UUNPKLO,
DL,
Op.getValueType(),
7066 case Intrinsic::aarch64_sve_clasta_n:
7067 return DAG.
getNode(AArch64ISD::CLASTA_N,
DL,
Op.getValueType(),
7068 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
7069 case Intrinsic::aarch64_sve_clastb_n:
7070 return DAG.
getNode(AArch64ISD::CLASTB_N,
DL,
Op.getValueType(),
7071 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
7072 case Intrinsic::aarch64_sve_lasta:
7073 return DAG.
getNode(AArch64ISD::LASTA,
DL,
Op.getValueType(),
7074 Op.getOperand(1),
Op.getOperand(2));
7075 case Intrinsic::aarch64_sve_lastb:
7076 return DAG.
getNode(AArch64ISD::LASTB,
DL,
Op.getValueType(),
7077 Op.getOperand(1),
Op.getOperand(2));
7078 case Intrinsic::aarch64_sve_tbl:
7079 return DAG.
getNode(AArch64ISD::TBL,
DL,
Op.getValueType(),
Op.getOperand(1),
7081 case Intrinsic::aarch64_sve_trn1:
7082 return DAG.
getNode(AArch64ISD::TRN1,
DL,
Op.getValueType(),
7083 Op.getOperand(1),
Op.getOperand(2));
7084 case Intrinsic::aarch64_sve_trn2:
7085 return DAG.
getNode(AArch64ISD::TRN2,
DL,
Op.getValueType(),
7086 Op.getOperand(1),
Op.getOperand(2));
7087 case Intrinsic::aarch64_sve_uzp1:
7088 return DAG.
getNode(AArch64ISD::UZP1,
DL,
Op.getValueType(),
7089 Op.getOperand(1),
Op.getOperand(2));
7090 case Intrinsic::aarch64_sve_uzp2:
7091 return DAG.
getNode(AArch64ISD::UZP2,
DL,
Op.getValueType(),
7092 Op.getOperand(1),
Op.getOperand(2));
7093 case Intrinsic::aarch64_sve_zip1:
7094 return DAG.
getNode(AArch64ISD::ZIP1,
DL,
Op.getValueType(),
7095 Op.getOperand(1),
Op.getOperand(2));
7096 case Intrinsic::aarch64_sve_zip2:
7097 return DAG.
getNode(AArch64ISD::ZIP2,
DL,
Op.getValueType(),
7098 Op.getOperand(1),
Op.getOperand(2));
7099 case Intrinsic::aarch64_sve_splice:
7100 return DAG.
getNode(AArch64ISD::SPLICE,
DL,
Op.getValueType(),
7101 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
7102 case Intrinsic::aarch64_sve_ptrue:
7103 return getPTrue(DAG,
DL,
Op.getValueType(),
Op.getConstantOperandVal(1));
7104 case Intrinsic::aarch64_sve_clz:
7105 return DAG.
getNode(AArch64ISD::CTLZ_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7106 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7107 case Intrinsic::aarch64_sme_cntsd: {
7113 case Intrinsic::aarch64_sve_cnt: {
7116 if (
Data.getValueType().isFloatingPoint())
7118 return DAG.
getNode(AArch64ISD::CTPOP_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7119 Op.getOperand(2),
Data,
Op.getOperand(1));
7121 case Intrinsic::aarch64_sve_dupq_lane:
7122 return LowerDUPQLane(
Op, DAG);
7123 case Intrinsic::aarch64_sve_convert_from_svbool:
7125 case Intrinsic::aarch64_sve_convert_to_svbool:
7127 case Intrinsic::aarch64_sve_convert_from_svcount:
7128 case Intrinsic::aarch64_sve_convert_to_svcount:
7130 case Intrinsic::aarch64_sve_fneg:
7131 return DAG.
getNode(AArch64ISD::FNEG_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7132 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7133 case Intrinsic::aarch64_sve_frintp:
7134 return DAG.
getNode(AArch64ISD::FCEIL_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7135 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7136 case Intrinsic::aarch64_sve_frintm:
7137 return DAG.
getNode(AArch64ISD::FFLOOR_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7138 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7139 case Intrinsic::aarch64_sve_frinti:
7140 return DAG.
getNode(AArch64ISD::FNEARBYINT_MERGE_PASSTHRU,
DL,
7141 Op.getValueType(),
Op.getOperand(2),
Op.getOperand(3),
7143 case Intrinsic::aarch64_sve_frintx:
7144 return DAG.
getNode(AArch64ISD::FRINT_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7145 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7146 case Intrinsic::aarch64_sve_frint32x:
7147 return DAG.
getNode(AArch64ISD::FRINT32_MERGE_PASSTHRU,
DL,
7148 Op.getValueType(),
Op.getOperand(2),
Op.getOperand(3),
7150 case Intrinsic::aarch64_sve_frint64x:
7151 return DAG.
getNode(AArch64ISD::FRINT64_MERGE_PASSTHRU,
DL,
7152 Op.getValueType(),
Op.getOperand(2),
Op.getOperand(3),
7154 case Intrinsic::aarch64_sve_frinta:
7155 return DAG.
getNode(AArch64ISD::FROUND_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7156 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7157 case Intrinsic::aarch64_sve_frintn:
7158 return DAG.
getNode(AArch64ISD::FROUNDEVEN_MERGE_PASSTHRU,
DL,
7159 Op.getValueType(),
Op.getOperand(2),
Op.getOperand(3),
7161 case Intrinsic::aarch64_sve_frintz:
7162 return DAG.
getNode(AArch64ISD::FTRUNC_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7163 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7164 case Intrinsic::aarch64_sve_frint32z:
7165 return DAG.
getNode(AArch64ISD::FTRUNC32_MERGE_PASSTHRU,
DL,
7166 Op.getValueType(),
Op.getOperand(2),
Op.getOperand(3),
7168 case Intrinsic::aarch64_sve_frint64z:
7169 return DAG.
getNode(AArch64ISD::FTRUNC64_MERGE_PASSTHRU,
DL,
7170 Op.getValueType(),
Op.getOperand(2),
Op.getOperand(3),
7172 case Intrinsic::aarch64_sve_ucvtf:
7173 return DAG.
getNode(AArch64ISD::UINT_TO_FP_MERGE_PASSTHRU,
DL,
7174 Op.getValueType(),
Op.getOperand(2),
Op.getOperand(3),
7176 case Intrinsic::aarch64_sve_scvtf:
7177 return DAG.
getNode(AArch64ISD::SINT_TO_FP_MERGE_PASSTHRU,
DL,
7178 Op.getValueType(),
Op.getOperand(2),
Op.getOperand(3),
7180 case Intrinsic::aarch64_sve_fcvtzu:
7181 return DAG.
getNode(AArch64ISD::FCVTZU_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7182 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7183 case Intrinsic::aarch64_sve_fcvtzs:
7184 return DAG.
getNode(AArch64ISD::FCVTZS_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7185 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7186 case Intrinsic::aarch64_sve_fsqrt:
7187 return DAG.
getNode(AArch64ISD::FSQRT_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7188 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7189 case Intrinsic::aarch64_sve_frecpx:
7190 return DAG.
getNode(AArch64ISD::FRECPX_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7191 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7192 case Intrinsic::aarch64_sve_frecpe_x:
7193 return DAG.
getNode(AArch64ISD::FRECPE,
DL,
Op.getValueType(),
7195 case Intrinsic::aarch64_sve_frecps_x:
7196 return DAG.
getNode(AArch64ISD::FRECPS,
DL,
Op.getValueType(),
7197 Op.getOperand(1),
Op.getOperand(2));
7198 case Intrinsic::aarch64_sve_frsqrte_x:
7199 return DAG.
getNode(AArch64ISD::FRSQRTE,
DL,
Op.getValueType(),
7201 case Intrinsic::aarch64_sve_frsqrts_x:
7202 return DAG.
getNode(AArch64ISD::FRSQRTS,
DL,
Op.getValueType(),
7203 Op.getOperand(1),
Op.getOperand(2));
7204 case Intrinsic::aarch64_sve_fabs:
7205 return DAG.
getNode(AArch64ISD::FABS_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7206 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7207 case Intrinsic::aarch64_sve_abs:
7208 return DAG.
getNode(AArch64ISD::ABS_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7209 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7210 case Intrinsic::aarch64_sve_neg:
7211 return DAG.
getNode(AArch64ISD::NEG_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7212 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7213 case Intrinsic::aarch64_sve_insr: {
7215 EVT ScalarTy =
Scalar.getValueType();
7216 if ((ScalarTy == MVT::i8) || (ScalarTy == MVT::i16))
7219 return DAG.
getNode(AArch64ISD::INSR,
DL,
Op.getValueType(),
7220 Op.getOperand(1), Scalar);
7222 case Intrinsic::aarch64_sve_rbit:
7223 return DAG.
getNode(AArch64ISD::BITREVERSE_MERGE_PASSTHRU,
DL,
7224 Op.getValueType(),
Op.getOperand(2),
Op.getOperand(3),
7226 case Intrinsic::aarch64_sve_revb:
7227 return DAG.
getNode(AArch64ISD::BSWAP_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7228 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7229 case Intrinsic::aarch64_sve_revh:
7230 return DAG.
getNode(AArch64ISD::REVH_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7231 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7232 case Intrinsic::aarch64_sve_revw:
7233 return DAG.
getNode(AArch64ISD::REVW_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7234 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7235 case Intrinsic::aarch64_sve_revd:
7236 return DAG.
getNode(AArch64ISD::REVD_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7237 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(1));
7238 case Intrinsic::aarch64_sve_sxtb:
7240 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7241 Op.getOperand(2),
Op.getOperand(3),
7245 case Intrinsic::aarch64_sve_sxth:
7247 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7248 Op.getOperand(2),
Op.getOperand(3),
7252 case Intrinsic::aarch64_sve_sxtw:
7254 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7255 Op.getOperand(2),
Op.getOperand(3),
7259 case Intrinsic::aarch64_sve_uxtb:
7261 AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7262 Op.getOperand(2),
Op.getOperand(3),
7266 case Intrinsic::aarch64_sve_uxth:
7268 AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7269 Op.getOperand(2),
Op.getOperand(3),
7273 case Intrinsic::aarch64_sve_uxtw:
7275 AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU,
DL,
Op.getValueType(),
7276 Op.getOperand(2),
Op.getOperand(3),
7280 case Intrinsic::localaddress: {
7282 const auto *RegInfo = Subtarget->getRegisterInfo();
7283 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
7285 Op.getSimpleValueType());
7288 case Intrinsic::eh_recoverfp: {
7293 SDValue IncomingFPOp =
Op.getOperand(2);
7298 "llvm.eh.recoverfp must take a function as the first argument");
7299 return IncomingFPOp;
7301 case Intrinsic::aarch64_neon_vsri:
7302 case Intrinsic::aarch64_neon_vsli:
7303 case Intrinsic::aarch64_sve_sri:
7304 case Intrinsic::aarch64_sve_sli: {
7305 EVT Ty =
Op.getValueType();
7312 bool IsShiftRight = IntNo == Intrinsic::aarch64_neon_vsri ||
7313 IntNo == Intrinsic::aarch64_sve_sri;
7314 unsigned Opcode = IsShiftRight ? AArch64ISD::VSRI : AArch64ISD::VSLI;
7315 return DAG.
getNode(Opcode,
DL, Ty,
Op.getOperand(1),
Op.getOperand(2),
7319 case Intrinsic::aarch64_neon_srhadd:
7320 case Intrinsic::aarch64_neon_urhadd:
7321 case Intrinsic::aarch64_neon_shadd:
7322 case Intrinsic::aarch64_neon_uhadd: {
7323 bool IsSignedAdd = (IntNo == Intrinsic::aarch64_neon_srhadd ||
7324 IntNo == Intrinsic::aarch64_neon_shadd);
7325 bool IsRoundingAdd = (IntNo == Intrinsic::aarch64_neon_srhadd ||
7326 IntNo == Intrinsic::aarch64_neon_urhadd);
7327 unsigned Opcode = IsSignedAdd
7330 return DAG.
getNode(Opcode,
DL,
Op.getValueType(),
Op.getOperand(1),
7333 case Intrinsic::aarch64_neon_saddlp:
7334 case Intrinsic::aarch64_neon_uaddlp: {
7335 unsigned Opcode = IntNo == Intrinsic::aarch64_neon_uaddlp
7336 ? AArch64ISD::UADDLP
7337 : AArch64ISD::SADDLP;
7338 return DAG.
getNode(Opcode,
DL,
Op.getValueType(),
Op.getOperand(1));
7340 case Intrinsic::aarch64_neon_sdot:
7341 case Intrinsic::aarch64_neon_udot:
7342 case Intrinsic::aarch64_sve_sdot:
7343 case Intrinsic::aarch64_sve_udot: {
7344 unsigned Opcode = (IntNo == Intrinsic::aarch64_neon_udot ||
7345 IntNo == Intrinsic::aarch64_sve_udot)
7348 return DAG.
getNode(Opcode,
DL,
Op.getValueType(),
Op.getOperand(1),
7349 Op.getOperand(2),
Op.getOperand(3));
7351 case Intrinsic::aarch64_neon_usdot:
7352 case Intrinsic::aarch64_sve_usdot: {
7353 return DAG.
getNode(AArch64ISD::USDOT,
DL,
Op.getValueType(),
7354 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
7356 case Intrinsic::aarch64_neon_saddlv:
7357 case Intrinsic::aarch64_neon_uaddlv: {
7358 EVT OpVT =
Op.getOperand(1).getValueType();
7359 EVT ResVT =
Op.getValueType();
7361 ((ResVT == MVT::i32 && (OpVT == MVT::v8i8 || OpVT == MVT::v16i8 ||
7362 OpVT == MVT::v8i16 || OpVT == MVT::v4i16)) ||
7363 (ResVT == MVT::i64 && (OpVT == MVT::v4i32 || OpVT == MVT::v2i32))) &&
7364 "Unexpected aarch64_neon_u/saddlv type");
7368 IntNo == Intrinsic::aarch64_neon_uaddlv ? AArch64ISD::UADDLV
7369 : AArch64ISD::SADDLV,
7370 DL, ResVT == MVT::i32 ? MVT::v4i32 : MVT::v2i64,
Op.getOperand(1));
7374 return EXTRACT_VEC_ELT;
7376 case Intrinsic::aarch64_cls:
7377 case Intrinsic::aarch64_cls64: {
7382 case Intrinsic::aarch64_neon_cls: {
7386 case Intrinsic::aarch64_sve_pmul:
7387 case Intrinsic::aarch64_neon_pmul:
7390 case Intrinsic::aarch64_sve_psel: {
7391 if (
Op.getValueType() != MVT::aarch64svcount)
7402bool AArch64TargetLowering::shouldExtendGSIndex(
EVT VT,
EVT &EltTy)
const {
7411bool AArch64TargetLowering::shouldRemoveExtendFromGSIndex(
SDValue Extend,
7432 if (LD->isVolatile())
7435 EVT MemVT = LD->getMemoryVT();
7436 if (MemVT != MVT::v2i8 && MemVT != MVT::v4i8 && MemVT != MVT::v2i16)
7439 Align Alignment = LD->getAlign();
7441 if (Subtarget.requiresStrictAlign() && Alignment < RequiredAlignment)
7447bool AArch64TargetLowering::isVectorLoadExtDesirable(
SDValue ExtVal)
const {
7455 if (!ExtVT.
isScalableVector() && !Subtarget->useSVEForFixedLengthVectors())
7471 unsigned NumExtMaskedLoads = 0;
7472 for (
auto *U : Ld->getMask()->users())
7474 NumExtMaskedLoads++;
7476 if (NumExtMaskedLoads <= 1)
7482 return PreExtScalarVT == MVT::i8 || PreExtScalarVT == MVT::i16 ||
7483 PreExtScalarVT == MVT::i32 || PreExtScalarVT == MVT::i64;
7488 std::map<std::tuple<bool, bool, bool>,
unsigned> AddrModes = {
7489 {std::make_tuple(
false,
false,
false),
7490 AArch64ISD::GLD1_MERGE_ZERO},
7491 {std::make_tuple(
false,
false,
true),
7492 AArch64ISD::GLD1_UXTW_MERGE_ZERO},
7493 {std::make_tuple(
false,
true,
false),
7494 AArch64ISD::GLD1_MERGE_ZERO},
7495 {std::make_tuple(
false,
true,
true),
7496 AArch64ISD::GLD1_SXTW_MERGE_ZERO},
7497 {std::make_tuple(
true,
false,
false),
7498 AArch64ISD::GLD1_SCALED_MERGE_ZERO},
7499 {std::make_tuple(
true,
false,
true),
7500 AArch64ISD::GLD1_UXTW_SCALED_MERGE_ZERO},
7501 {std::make_tuple(
true,
true,
false),
7502 AArch64ISD::GLD1_SCALED_MERGE_ZERO},
7503 {std::make_tuple(
true,
true,
true),
7504 AArch64ISD::GLD1_SXTW_SCALED_MERGE_ZERO},
7506 auto Key = std::make_tuple(IsScaled, IsSigned, NeedsExtend);
7507 return AddrModes.find(
Key)->second;
7515 case AArch64ISD::GLD1_MERGE_ZERO:
7516 return AArch64ISD::GLD1S_MERGE_ZERO;
7517 case AArch64ISD::GLD1_IMM_MERGE_ZERO:
7518 return AArch64ISD::GLD1S_IMM_MERGE_ZERO;
7519 case AArch64ISD::GLD1_UXTW_MERGE_ZERO:
7520 return AArch64ISD::GLD1S_UXTW_MERGE_ZERO;
7521 case AArch64ISD::GLD1_SXTW_MERGE_ZERO:
7522 return AArch64ISD::GLD1S_SXTW_MERGE_ZERO;
7523 case AArch64ISD::GLD1_SCALED_MERGE_ZERO:
7524 return AArch64ISD::GLD1S_SCALED_MERGE_ZERO;
7525 case AArch64ISD::GLD1_UXTW_SCALED_MERGE_ZERO:
7526 return AArch64ISD::GLD1S_UXTW_SCALED_MERGE_ZERO;
7527 case AArch64ISD::GLD1_SXTW_SCALED_MERGE_ZERO:
7528 return AArch64ISD::GLD1S_SXTW_SCALED_MERGE_ZERO;
7543 EVT VT =
Op.getValueType();
7567 EVT IndexVT =
Index.getValueType();
7579 assert(Subtarget->useSVEForFixedLengthVectors() &&
7580 "Cannot lower when not using SVE for fixed vectors!");
7589 Index.getValueType().getVectorElementType() == MVT::i64 ||
7590 Mask.getValueType().getVectorElementType() == MVT::i64)
7656 EVT IndexVT =
Index.getValueType();
7668 assert(Subtarget->useSVEForFixedLengthVectors() &&
7669 "Cannot lower when not using SVE for fixed vectors!");
7681 Index.getValueType().getVectorElementType() == MVT::i64 ||
7682 Mask.getValueType().getVectorElementType() == MVT::i64)
7692 if (PromotedVT != VT)
7717 assert(LoadNode &&
"Expected custom lowering of a masked load node");
7718 EVT VT =
Op->getValueType(0);
7721 return LowerFixedLengthVectorMLoadToSVE(
Op, DAG);
7741 if ((!Subtarget->isSVEAvailable() || !Subtarget->hasSVE2p2()) &&
7742 (!Subtarget->isSVEorStreamingSVEAvailable() || !Subtarget->hasSME2p2()))
7781 assert(MemVT == MVT::v4i8 && VT == MVT::v4i16);
7804 return DAG.
getStore(ST->getChain(),
DL, ExtractTrunc,
7805 ST->getBasePtr(), ST->getMemOperand());
7811 MVT DestVT =
Op.getSimpleValueType();
7815 unsigned SrcAS =
N->getSrcAddressSpace();
7816 unsigned DestAS =
N->getDestAddressSpace();
7817 assert(SrcAS != DestAS &&
7818 "addrspacecast must be between different address spaces");
7821 "addrspacecast must be between different ptr sizes");
7846 if (!
DL.isLittleEndian())
7850 if (DataType->isIntegerTy(64))
7858 unsigned NumElements = DataTypeTy->getNumElements();
7859 unsigned EltSizeBits = DataTypeTy->getElementType()->getScalarSizeInBits();
7865 unsigned TotalSizeBits = DataTypeTy->getPrimitiveSizeInBits().getFixedValue();
7869 if (TotalSizeBits == 64u || TotalSizeBits == 128u)
7873 if (TotalSizeBits == 256u && (EltSizeBits == 8u || EltSizeBits == 16u ||
7874 EltSizeBits == 32u || EltSizeBits == 64u))
7887 assert(StoreNode &&
"Expected a store operation");
7914 StoreNode->
getValue(), EC.getKnownMinValue() / 2);
7917 {StoreNode->getChain(), DAG.getBitcast(MVT::v2i64, Lo),
7918 DAG.getBitcast(MVT::v2i64, Hi), StoreNode->getBasePtr()},
7922 "Lowering should be consistent with legality");
7943 "invalid SVE multi-vector size");
7948 Info.LoadIntID = Intrinsic::aarch64_sve_ld1_pn_x2;
7949 Info.StoreIntID = Intrinsic::aarch64_sve_st1_pn_x2;
7952 Info.LoadIntID = Intrinsic::aarch64_sve_ld1_pn_x4;
7953 Info.StoreIntID = Intrinsic::aarch64_sve_st1_pn_x4;
7976 if (
Value->isUndef())
7990 for (
unsigned i = 0; i != MultiVecInfo.
NumVecs; ++i)
8026 for (
unsigned I = 0;
I != MultiVecInfo.
NumVecs; ++
I)
8040 assert (StoreNode &&
"Can only custom lower store nodes");
8044 EVT VT =
Value.getValueType();
8048 if (
auto MaybeSTNP =
LowerNTStore(StoreNode, VT, MemVT, Dl, DAG))
8058 Subtarget->useSVEForFixedLengthVectors()))
8059 return LowerFixedLengthVectorStoreToSVE(
Op, DAG);
8071 MemVT == MVT::v4i8) {
8074 }
else if (MemVT == MVT::i128 && StoreNode->
isVolatile()) {
8075 return LowerStore128(
Op, DAG);
8076 }
else if (MemVT == MVT::i64x8) {
8081 EVT PtrVT =
Base.getValueType();
8082 for (
unsigned i = 0; i < 8; i++) {
8103 bool IsStoreRelease =
8106 assert((Subtarget->hasFeature(AArch64::FeatureLSE2) &&
8107 Subtarget->hasFeature(AArch64::FeatureRCPC3) && IsStoreRelease) ||
8117 unsigned Opcode = IsStoreRelease ? AArch64ISD::STILP : AArch64ISD::STP;
8119 std::swap(StoreValue.first, StoreValue.second);
8122 {StoreNode->getChain(), StoreValue.first, StoreValue.second,
8123 StoreNode->getBasePtr()},
8135 EVT MemVT =
Load->getMemoryVT();
8136 EVT ResVT =
Load->getValueType(0);
8142 switch (
Load->getExtensionType()) {
8164 DAG.
getLoad(ScalarLoadType,
DL, Chain, BasePtr, PtrInfo, Alignment);
8176 while (CurrentEltBits < DstEltBits) {
8178 CurrentNumElts = CurrentNumElts / 2;
8183 CurrentEltBits = CurrentEltBits * 2;
8186 Res = DAG.
getNode(ExtOpcode,
DL, ExtVT, Res);
8189 if (CurrentNumElts != NumElts) {
8201 assert(LoadNode &&
"Expected custom lowering of a load node");
8206 bool OverrideNeon = !Subtarget->isNeonAvailable() ||
8209 return LowerFixedLengthVectorLoadToSVE(
Op, DAG);
8218 EVT PtrVT =
Base.getValueType();
8219 for (
unsigned i = 0; i < 8; i++) {
8225 Ops.push_back(Part);
8235SDValue AArch64TargetLowering::LowerFixedLengthVectorCompressToSVE(
8238 EVT VT =
Op.getValueType();
8253 EVT VT =
Op.getValueType();
8255 return LowerFixedLengthVectorCompressToSVE(
Op, DAG);
8261 EVT MaskVT =
Mask.getValueType();
8288 EVT VT =
Op.getValueType();
8289 assert((VT == MVT::v4i16 || VT == MVT::v8i16 || VT == MVT::v2i32 ||
8290 VT == MVT::v4i32) &&
8291 "Unexpected type for SMULFIXSAT lowering");
8293 unsigned Scale =
Op.getConstantOperandVal(2);
8297 return DAG.
getNode(AArch64ISD::SQDMULH, SDLoc(
Op), VT,
Op.getOperand(0),
8303 MVT VT =
Op.getSimpleValueType();
8306 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::ABS_MERGE_PASSTHRU);
8314 return DAG.
getNode(AArch64ISD::CSEL,
DL, VT,
Op.getOperand(0), Neg,
8327 return DAG.
getNode(AArch64ISD::BRCOND,
DL, MVT::Other, Chain, Dest, CCVal,
8342 MVT VT =
Op.getSimpleValueType();
8346 if (NewShiftNo == 0)
8347 return Op.getOperand(0);
8356 if (NewShiftNo == 0)
8357 return Op.getOperand(1);
8359 if (ShiftNo->getZExtValue() == NewShiftNo)
8374 EVT XScalarTy =
X.getValueType();
8379 switch (
Op.getSimpleValueType().SimpleTy) {
8388 ExpVT = MVT::nxv4i32;
8392 ExpVT = MVT::nxv2i64;
8410 if (
X.getValueType() != XScalarTy)
8418 return Op.getOperand(0);
8453 const char FptrReg = 0x11;
8459 Chain,
DL, DAG.
getConstant(0x58000080u | NestReg,
DL, MVT::i32), Addr,
8460 MachinePointerInfo(TrmpAddr));
8465 Chain,
DL, DAG.
getConstant(0x580000b0u | FptrReg,
DL, MVT::i32), Addr,
8466 MachinePointerInfo(TrmpAddr, 4));
8472 MachinePointerInfo(TrmpAddr, 8));
8477 DAG.
getStore(Chain,
DL, Nest, Addr, MachinePointerInfo(TrmpAddr, 16));
8482 DAG.
getStore(Chain,
DL, FPtr, Addr, MachinePointerInfo(TrmpAddr, 24));
8496 EVT VT =
Op.getValueType();
8498 (Subtarget->hasSVEB16B16() &&
8499 Subtarget->isNonStreamingSVEorSME2Available()))
8500 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FMUL_PRED);
8502 assert(Subtarget->hasBF16() &&
"Expected +bf16 for custom FMUL lowering");
8503 assert((VT == MVT::nxv4bf16 || VT == MVT::nxv8bf16 || VT == MVT::v8bf16) &&
8504 "Unexpected FMUL VT");
8507 return [&, IID](EVT VT,
auto...
Ops) {
8514 EVT SrcVT =
Value.getValueType();
8525 auto FCVT = MakeGetIntrinsic(Intrinsic::aarch64_sve_fcvt_bf16f32_v2);
8526 auto FCVTNT = MakeGetIntrinsic(Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2);
8531 MakeGetIntrinsic(UseSVEBFMLAL ? Intrinsic::aarch64_sve_bfmlalb
8532 : Intrinsic::aarch64_neon_bfmlalb);
8534 MakeGetIntrinsic(UseSVEBFMLAL ? Intrinsic::aarch64_sve_bfmlalt
8535 : Intrinsic::aarch64_neon_bfmlalt);
8537 EVT AccVT = UseSVEBFMLAL ? MVT::nxv4f32 : MVT::v4f32;
8550 LHS = Reinterpret(
LHS, MVT::nxv8bf16);
8551 RHS = Reinterpret(
RHS, MVT::nxv8bf16);
8554 SDValue BottomF32 = Reinterpret(BFMLALB(AccVT, Zero,
LHS,
RHS), MVT::nxv4f32);
8556 FCVT(MVT::nxv8bf16, DAG.
getPOISON(MVT::nxv8bf16), Pg, BottomF32);
8558 if (VT == MVT::nxv4bf16)
8559 return Reinterpret(BottomBF16, VT);
8561 SDValue TopF32 = Reinterpret(BFMLALT(AccVT, Zero,
LHS,
RHS), MVT::nxv4f32);
8562 SDValue TopBF16 = FCVTNT(MVT::nxv8bf16, BottomBF16, Pg, TopF32);
8563 return Reinterpret(TopBF16, VT);
8570 EVT VT =
Op.getValueType();
8573 assert(VT.
isVector() &&
"Scalar fma lowering should be handled by patterns");
8576 if (VT != MVT::v8f16 && VT != MVT::v4f32 && VT != MVT::v2f64)
8577 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FMA_PRED);
8581 ? LowerToPredicatedOp(
Op, DAG, AArch64ISD::FMA_PRED)
8591 auto ConvertToScalableFnegMt = [&](
SDValue Op) {
8593 Op = LowerToPredicatedOp(
Op, DAG, AArch64ISD::FNEG_MERGE_PASSTHRU);
8597 OpA = ConvertToScalableFnegMt(OpA);
8598 OpB = ConvertToScalableFnegMt(OpB);
8599 OpC = ConvertToScalableFnegMt(OpC);
8602 DAG.
getNode(AArch64ISD::FMA_PRED,
DL, ContainerVT, Pg, OpA, OpB, OpC);
8634 EVT VT =
Op.getValueType();
8636 assert((VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8 ||
8637 VT == MVT::v4i32 || VT == MVT::nxv8i16 || VT == MVT::nxv2i64) &&
8642 if (VT == MVT::v4i32) {
8652 if (VT == MVT::nxv2i64) {
8654 DAG.
getNode(AArch64ISD::NVCAST,
DL, MVT::nxv4i32,
Op.getOperand(0));
8656 DAG.
getNode(AArch64ISD::NVCAST,
DL, MVT::nxv4i32,
Op.getOperand(1));
8660 if ((Subtarget->hasSVE2() || Subtarget->hasSME()) &&
8667 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, PMULLB);
8670 if (Subtarget->hasSVEAES() &&
8671 (Subtarget->isSVEAvailable() || Subtarget->hasSSVE_AES()))
8674 if (Subtarget->hasSVE2() || Subtarget->hasSME()) {
8676 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, CrossCLMUL);
8682 if (VT == MVT::nxv8i16) {
8684 DAG.
getNode(AArch64ISD::NVCAST,
DL, MVT::nxv16i8,
Op.getOperand(0));
8686 DAG.
getNode(AArch64ISD::NVCAST,
DL, MVT::nxv16i8,
Op.getOperand(1));
8696 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, PMULLB);
8700 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, CrossCLMUL);
8704 EVT CLMULTy = VT == MVT::i8 ? MVT::v8i8 : MVT::v1i64;
8705 EVT ExtractTy = VT == MVT::i64 ? MVT::i64 : MVT::i32;
8711 if (VecVT != CLMULTy) {
8716 if (ExtractTy == MVT::i32)
8721 if (ExtractTy != VT)
8723 return ExtractVecElt;
8731 switch (
Op.getOpcode()) {
8737 return LowerLOOP_DEPENDENCE_MASK(
Op, DAG);
8739 return LowerBITCAST(
Op, DAG);
8741 return LowerGlobalAddress(
Op, DAG);
8743 return LowerGlobalTLSAddress(
Op, DAG);
8745 return LowerPtrAuthGlobalAddress(
Op, DAG);
8747 return LowerADJUST_TRAMPOLINE(
Op, DAG);
8749 return LowerINIT_TRAMPOLINE(
Op, DAG);
8753 return LowerSETCC(
Op, DAG);
8755 return LowerSETCCCARRY(
Op, DAG);
8759 return LowerBR_CC(
Op, DAG);
8761 return LowerSELECT(
Op, DAG);
8763 return LowerSELECT_CC(
Op, DAG);
8765 return LowerJumpTable(
Op, DAG);
8767 return LowerBR_JT(
Op, DAG);
8769 return LowerBRIND(
Op, DAG);
8771 return LowerConstantPool(
Op, DAG);
8773 return LowerBlockAddress(
Op, DAG);
8775 return LowerVASTART(
Op, DAG);
8777 return LowerVACOPY(
Op, DAG);
8779 return LowerVAARG(
Op, DAG);
8796 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FADD_PRED);
8798 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::STRICT_FADD_PRED);
8800 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FSUB_PRED);
8802 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::STRICT_FSUB_PRED);
8804 return LowerFMUL(
Op, DAG);
8806 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::STRICT_FMUL_PRED);
8808 return LowerFMA(
Op, DAG);
8810 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::STRICT_FMA_PRED);
8812 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FDIV_PRED);
8814 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::STRICT_FDIV_PRED);
8816 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FNEG_MERGE_PASSTHRU);
8818 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FCEIL_MERGE_PASSTHRU);
8820 return LowerToPredicatedOp(
Op, DAG,
8821 AArch64ISD::STRICT_FCEIL_MERGE_PASSTHRU);
8823 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FFLOOR_MERGE_PASSTHRU);
8825 return LowerToPredicatedOp(
Op, DAG,
8826 AArch64ISD::STRICT_FFLOOR_MERGE_PASSTHRU);
8828 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FNEARBYINT_MERGE_PASSTHRU);
8830 return LowerToPredicatedOp(
Op, DAG,
8831 AArch64ISD::STRICT_FNEARBYINT_MERGE_PASSTHRU);
8833 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FRINT_MERGE_PASSTHRU);
8835 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FROUND_MERGE_PASSTHRU);
8837 return LowerToPredicatedOp(
Op, DAG,
8838 AArch64ISD::STRICT_FROUND_MERGE_PASSTHRU);
8840 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FROUNDEVEN_MERGE_PASSTHRU);
8842 return LowerToPredicatedOp(
Op, DAG,
8843 AArch64ISD::STRICT_FROUNDEVEN_MERGE_PASSTHRU);
8845 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FTRUNC_MERGE_PASSTHRU);
8847 return LowerToPredicatedOp(
Op, DAG,
8848 AArch64ISD::STRICT_FTRUNC_MERGE_PASSTHRU);
8850 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FSQRT_MERGE_PASSTHRU);
8852 return LowerToPredicatedOp(
Op, DAG,
8853 AArch64ISD::STRICT_FSQRT_MERGE_PASSTHRU);
8855 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FABS_MERGE_PASSTHRU);
8858 return LowerFP_ROUND(
Op, DAG);
8861 return LowerFP_EXTEND(
Op, DAG);
8863 return LowerFRAMEADDR(
Op, DAG);
8865 return LowerSPONENTRY(
Op, DAG);
8867 return LowerRETURNADDR(
Op, DAG);
8869 return LowerADDROFRETURNADDR(
Op, DAG);
8871 return LowerCONCAT_VECTORS(
Op, DAG);
8873 return LowerINSERT_VECTOR_ELT(
Op, DAG);
8875 return LowerEXTRACT_VECTOR_ELT(
Op, DAG);
8877 return LowerBUILD_VECTOR(
Op, DAG);
8880 return LowerEXTEND_VECTOR_INREG(
Op, DAG);
8882 return LowerZERO_EXTEND_VECTOR_INREG(
Op, DAG);
8884 return LowerVECTOR_SHUFFLE(
Op, DAG);
8886 return LowerSPLAT_VECTOR(
Op, DAG);
8888 return LowerEXTRACT_SUBVECTOR(
Op, DAG);
8890 return LowerINSERT_SUBVECTOR(
Op, DAG);
8895 return LowerDIV(
Op, DAG);
8900 return LowerMinMax(
Op, DAG);
8904 return LowerVectorSRA_SRL_SHL(
Op, DAG);
8908 return LowerShiftParts(
Op, DAG);
8911 return LowerCTPOP_PARITY(
Op, DAG);
8913 return LowerFCOPYSIGN(
Op, DAG);
8915 return LowerVectorOR(
Op, DAG);
8917 return LowerXOR(
Op, DAG);
8924 return LowerINT_TO_FP(
Op, DAG);
8929 return LowerFP_TO_INT(
Op, DAG);
8932 return LowerFP_TO_INT_SAT(
Op, DAG);
8934 return LowerGET_ROUNDING(
Op, DAG);
8936 return LowerSET_ROUNDING(
Op, DAG);
8938 return LowerGET_FPMODE(
Op, DAG);
8940 return LowerSET_FPMODE(
Op, DAG);
8942 return LowerRESET_FPMODE(
Op, DAG);
8944 return LowerMUL(
Op, DAG);
8946 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::MULHS_PRED);
8948 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::MULHU_PRED);
8950 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
8952 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
8954 return LowerINTRINSIC_VOID(
Op, DAG);
8957 assert(Subtarget->hasLSE2() || Subtarget->hasRCPC3());
8958 return LowerStore128(
Op, DAG);
8962 return LowerSTORE(
Op, DAG);
8964 return LowerMSTORE(
Op, DAG);
8966 return LowerMGATHER(
Op, DAG);
8968 return LowerMSCATTER(
Op, DAG);
8970 return LowerVECREDUCE_SEQ_FADD(
Op, DAG);
8984 return LowerVECREDUCE(
Op, DAG);
8987 return LowerVECREDUCE_MUL(
Op, DAG);
8989 return LowerATOMIC_LOAD_AND(
Op, DAG);
8991 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
8993 return LowerVSCALE(
Op, DAG);
8995 return LowerVECTOR_COMPRESS(
Op, DAG);
8999 return LowerFixedLengthVectorIntExtendToSVE(
Op, DAG);
9006 if ((ExtraEltVT != MVT::i8) && (ExtraEltVT != MVT::i16) &&
9007 (ExtraEltVT != MVT::i32) && (ExtraEltVT != MVT::i64))
9010 return LowerToPredicatedOp(
Op, DAG,
9011 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU);
9014 return LowerTRUNCATE(
Op, DAG);
9016 return LowerMLOAD(
Op, DAG);
9018 return LowerLOAD(
Op, DAG);
9022 return LowerToScalableOp(
Op, DAG);
9024 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FMAX_PRED);
9026 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::STRICT_FMAX_PRED);
9029 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FMAXNM_PRED);
9031 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::STRICT_FMAXNM_PRED);
9033 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FMIN_PRED);
9035 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::STRICT_FMIN_PRED);
9038 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::FMINNM_PRED);
9040 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::STRICT_FMINNM_PRED);
9042 return LowerFixedLengthVectorSelectToSVE(
Op, DAG);
9044 return LowerABS(
Op, DAG);
9046 return LowerSMULFIXSAT(
Op, DAG);
9048 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::ABDS_PRED);
9050 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::ABDU_PRED);
9052 return LowerAVG(
Op, DAG, AArch64ISD::HADDS_PRED);
9054 return LowerAVG(
Op, DAG, AArch64ISD::HADDU_PRED);
9056 return LowerAVG(
Op, DAG, AArch64ISD::RHADDS_PRED);
9058 return LowerAVG(
Op, DAG, AArch64ISD::RHADDU_PRED);
9060 return LowerBitreverse(
Op, DAG);
9062 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::BSWAP_MERGE_PASSTHRU);
9064 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::CTLZ_MERGE_PASSTHRU);
9066 return LowerCTTZ(
Op, DAG);
9069 return LowerVECTOR_SPLICE(
Op, DAG);
9071 return LowerVECTOR_DEINTERLEAVE(
Op, DAG);
9073 return LowerVECTOR_INTERLEAVE(
Op, DAG);
9075 return LowerGET_ACTIVE_LANE_MASK(
Op, DAG);
9080 if (
Op.getValueType().isVector())
9081 return LowerVectorXRINT(
Op, DAG);
9085 assert((
Op.getOperand(0).getValueType() == MVT::f16 ||
9086 Op.getOperand(0).getValueType() == MVT::bf16) &&
9087 "Expected custom lowering of rounding operations only for f16");
9090 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
9096 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
9097 Op.getOperand(1).getValueType() == MVT::bf16) &&
9098 "Expected custom lowering of rounding operations only for f16");
9101 {
Op.getOperand(0),
Op.getOperand(1)});
9102 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
9103 {Ext.getValue(1), Ext.getValue(0)});
9106 assert(
Op.getOperand(2).getValueType() == MVT::i128 &&
9107 "WRITE_REGISTER custom lowering is only for 128-bit sysregs");
9112 std::pair<SDValue, SDValue> Pair =
9117 SysRegName, Pair.first, Pair.second);
9127 return LowerVECTOR_HISTOGRAM(
Op, DAG);
9132 return LowerPARTIAL_REDUCE_MLA(
Op, DAG);
9134 return LowerCLMUL(
Op, DAG);
9139 EVT VT =
Op.getValueType();
9141 ? Intrinsic::aarch64_sve_bext_x
9142 : Intrinsic::aarch64_sve_bdep_x;
9145 assert((VT == MVT::i32 || VT == MVT::i64) &&
"Unexpected scalar type");
9146 EVT SveVT = VT == MVT::i64 ? MVT::nxv2i64 : MVT::nxv4i32;
9159 Op.getOperand(0),
Op.getOperand(1));
9162 return LowerFCANONICALIZE(
Op, DAG);
9180 DAG.
getNode(AArch64ISD::CTTZ_ELTS,
DL, MVT::i64, Pg, CttzOp);
9187 return !Subtarget->useSVEForFixedLengthVectors();
9191 EVT VT,
bool OverrideNEON)
const {
9218 return Subtarget->isSVEorStreamingSVEAvailable();
9225 if (!Subtarget->useSVEForFixedLengthVectors())
9245 unsigned Opcode =
N->getOpcode();
9250 unsigned IID =
N->getConstantOperandVal(0);
9251 if (IID < Intrinsic::num_intrinsics)
9265 if (IID == Intrinsic::aarch64_neon_umull ||
9267 IID == Intrinsic::aarch64_neon_smull ||
9276 bool IsVarArg)
const {
9299 if (Subtarget->isTargetWindows()) {
9301 if (Subtarget->isWindowsArm64EC())
9307 if (!Subtarget->isTargetDarwin())
9315 if (Subtarget->isWindowsArm64EC())
9321 if (Subtarget->isWindowsArm64EC())
9345 if (Subtarget->isWindowsArm64EC())
9362 auto &FuncInfo = *MF.
getInfo<AArch64FunctionInfo>();
9364 SMEAttrs SMEFnAttrs = FuncInfo.getSMEFnAttrs();
9383 if (SMEFnAttrs.hasStreamingInterfaceOrBody())
9386 else if (SMEFnAttrs.hasStreamingCompatibleInterface())
9392SDValue AArch64TargetLowering::LowerFormalArguments(
9400 Subtarget->isCallingConvWin64(
F.getCallingConv(),
F.isVarArg());
9402 (isVarArg && Subtarget->isWindowsArm64EC());
9403 AArch64FunctionInfo *FuncInfo = MF.
getInfo<AArch64FunctionInfo>();
9408 if (
any_of(Outs, [](ISD::OutputArg &Out){
return Out.VT.isScalableVector(); }))
9413 CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.
getContext());
9421 unsigned NumArgs = Ins.
size();
9423 unsigned CurArgIdx = 0;
9424 bool UseVarArgCC =
false;
9426 UseVarArgCC = isVarArg;
9430 for (
unsigned i = 0; i != NumArgs; ++i) {
9431 MVT ValVT = Ins[i].VT;
9432 if (Ins[i].isOrigArg()) {
9433 std::advance(CurOrigArg, Ins[i].getOrigArgIndex() - CurArgIdx);
9434 CurArgIdx = Ins[i].getOrigArgIndex();
9441 if (ActualMVT == MVT::i1 || ActualMVT == MVT::i8)
9443 else if (ActualMVT == MVT::i16)
9447 Ins[i].OrigTy, CCInfo);
9448 assert(!Res &&
"Call operand has unhandled type");
9453 bool IsLocallyStreaming =
9454 !
Attrs.hasStreamingInterface() &&
Attrs.hasStreamingBody();
9458 unsigned ExtraArgLocs = 0;
9459 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
9460 CCValAssign &VA = ArgLocs[i - ExtraArgLocs];
9462 if (Ins[i].
Flags.isByVal()) {
9466 int Size = Ins[i].Flags.getByValSize();
9467 unsigned NumRegs = (
Size + 7) / 8;
9479 if (Ins[i].
Flags.isSwiftAsync())
9480 MF.
getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(
true);
9488 if (RegVT == MVT::i32)
9489 RC = &AArch64::GPR32RegClass;
9490 else if (RegVT == MVT::i64)
9491 RC = &AArch64::GPR64RegClass;
9492 else if (RegVT == MVT::f16 || RegVT == MVT::bf16)
9493 RC = &AArch64::FPR16RegClass;
9494 else if (RegVT == MVT::f32)
9495 RC = &AArch64::FPR32RegClass;
9497 RC = &AArch64::FPR64RegClass;
9499 RC = &AArch64::FPR128RegClass;
9503 RC = &AArch64::PPRRegClass;
9504 }
else if (RegVT == MVT::aarch64svcount) {
9506 RC = &AArch64::PPRRegClass;
9509 RC = &AArch64::ZPRRegClass;
9516 if (IsLocallyStreaming) {
9531 DAG.
getNode(AArch64ISD::COALESCER_BARRIER,
DL,
9550 "Indirect arguments should be scalable on most subtargets");
9572 uint32_t BEAlign = 0;
9573 if (!Subtarget->isLittleEndian() && ArgSize < 8 &&
9574 !Ins[i].Flags.isInConsecutiveRegs())
9575 BEAlign = 8 - ArgSize;
9578 MachinePointerInfo PtrInfo;
9584 unsigned ObjOffset = ArgOffset + BEAlign;
9614 "Indirect arguments should be scalable on most subtargets");
9634 Subtarget->isWindowsArm64EC()) &&
9635 "Indirect arguments should be scalable on most subtargets");
9638 unsigned NumParts = 1;
9639 if (Ins[i].
Flags.isInConsecutiveRegs()) {
9640 while (!Ins[i + NumParts - 1].
Flags.isInConsecutiveRegsLast())
9649 while (NumParts > 0) {
9650 ArgValue = DAG.
getLoad(PartLoad,
DL, Chain, Ptr, MachinePointerInfo());
9663 if (Subtarget->isTargetILP32() && Ins[i].Flags.isPointer())
9669 if (Ins[i].isOrigArg()) {
9670 Argument *OrigArg =
F.getArg(Ins[i].getOrigArgIndex());
9672 if (!Ins[i].
Flags.isZExt()) {
9673 ArgValue = DAG.
getNode(AArch64ISD::ASSERT_ZEXT_BOOL,
DL,
9684 if (
Attrs.hasStreamingCompatibleInterface()) {
9686 DAG.
getNode(AArch64ISD::ENTRY_PSTATE_SM,
DL,
9687 DAG.
getVTList(MVT::i64, MVT::Other), {Chain});
9699 if (IsLocallyStreaming) {
9700 if (
Attrs.hasStreamingCompatibleInterface())
9709 for (
unsigned I=0;
I<InVals.
size(); ++
I) {
9721 if (!Subtarget->isTargetDarwin() || IsWin64) {
9727 saveVarArgRegisters(CCInfo, DAG,
DL, Chain);
9731 unsigned VarArgsOffset = CCInfo.getStackSize();
9734 alignTo(VarArgsOffset, Subtarget->isTargetILP32() ? 4 : 8);
9745 SmallVectorImpl<ForwardedRegister> &Forwards =
9747 CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes,
9751 if (!CCInfo.isAllocated(AArch64::X8)) {
9753 Forwards.
push_back(ForwardedRegister(X8VReg, AArch64::X8, MVT::i64));
9762 for (
unsigned I = 0,
E = Ins.
size();
I !=
E; ++
I) {
9764 Ins[
I].Flags.isInReg()) &&
9765 Ins[
I].Flags.isSRet()) {
9780 unsigned StackArgSize = CCInfo.getStackSize();
9782 if (DoesCalleeRestoreStack(CallConv, TailCallOpt)) {
9786 StackArgSize =
alignTo(StackArgSize, 16);
9800 if (Subtarget->hasCustomCallingConv())
9801 Subtarget->getRegisterInfo()->UpdateCustomCalleeSavedRegs(MF);
9805 if (
Attrs.hasZAState()) {
9809 }
else if (
Attrs.hasAgnosticZAInterface()) {
9810 RTLIB::Libcall LC = RTLIB::SMEABI_SME_STATE_SIZE;
9815 auto *RetTy = EVT(MVT::i64).getTypeForEVT(*DAG.
getContext());
9816 TargetLowering::CallLoweringInfo CLI(DAG);
9817 CLI.setDebugLoc(
DL).setChain(Chain).setLibCallee(
9825 {Chain, Size, DAG.getConstant(1, DL, MVT::i64)});
9831 Chain = DAG.
getNode(AArch64ISD::SME_STATE_ALLOC,
DL,
9839 for (
const ISD::InputArg &
I : Ins) {
9840 if (
I.Flags.isSwiftSelf() ||
I.Flags.isSwiftError() ||
9841 I.Flags.isSwiftAsync()) {
9845 "Swift attributes can't be used with preserve_none",
9855void AArch64TargetLowering::saveVarArgRegisters(
CCState &CCInfo,
9861 AArch64FunctionInfo *FuncInfo = MF.
getInfo<AArch64FunctionInfo>();
9865 Subtarget->isCallingConvWin64(
F.getCallingConv(),
F.isVarArg());
9871 if (Subtarget->isWindowsArm64EC()) {
9878 unsigned GPRSaveSize = 8 * (NumGPRArgRegs - FirstVariadicGPR);
9880 if (GPRSaveSize != 0) {
9883 if (GPRSaveSize & 15)
9890 if (Subtarget->isWindowsArm64EC()) {
9903 for (
unsigned i = FirstVariadicGPR; i < NumGPRArgRegs; ++i) {
9909 MF, GPRIdx, (i - FirstVariadicGPR) * 8)
9919 if (Subtarget->hasFPARMv8() && !IsWin64) {
9921 const unsigned NumFPRArgRegs =
FPRArgRegs.size();
9924 unsigned FPRSaveSize = 16 * (NumFPRArgRegs - FirstVariadicFPR);
9926 if (FPRSaveSize != 0) {
9931 for (
unsigned i = FirstVariadicFPR; i < NumFPRArgRegs; ++i) {
9946 if (!MemOps.
empty()) {
9953SDValue AArch64TargetLowering::LowerCallResult(
9957 SDValue ThisVal,
bool RequiresSMChange)
const {
9958 DenseMap<unsigned, SDValue> CopiedRegs;
9960 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
9961 CCValAssign VA = RVLocs[i];
9965 if (i == 0 && isThisReturn) {
9967 "unexpected return calling convention register assignment");
10003 Val = DAG.
getNode(AArch64ISD::COALESCER_BARRIER,
DL,
10070 unsigned NumArgs = Outs.
size();
10078 if (IsArm64ECVarArgExitThunk) {
10081 "x4/x5 (pointer/length) arguments");
10085 for (
unsigned i = 0; i != NumArgs; ++i) {
10086 MVT ArgVT = Outs[i].VT;
10089 bool UseVarArgCC =
false;
10093 if (IsCalleeWin64) {
10094 UseVarArgCC =
true;
10096 UseVarArgCC = ArgFlags.
isVarArg();
10100 if (!UseVarArgCC) {
10107 if (ActualMVT == MVT::i1 || ActualMVT == MVT::i8)
10109 else if (ActualMVT == MVT::i16)
10117 Outs[i].OrigTy, CCInfo);
10118 assert(!Res &&
"Call operand has unhandled type");
10133bool AArch64TargetLowering::isEligibleForTailCallOptimization(
10134 const CallLoweringInfo &CLI)
const {
10140 bool IsVarArg = CLI.IsVarArg;
10144 const SelectionDAG &DAG = CLI.DAG;
10164 MF.
getInfo<AArch64FunctionInfo>()->isSVECC())
10167 bool CCMatch = CallerCC == CalleeCC;
10182 if (i->hasByValAttr())
10191 if (i->hasInRegAttr()) {
10192 unsigned ArgIdx = i - CallerF.
arg_begin();
10193 if (!CLI.CB || CLI.CB->arg_size() <= ArgIdx)
10195 AttributeSet
Attrs = CLI.CB->getParamAttributes(ArgIdx);
10196 if (!
Attrs.hasAttribute(Attribute::InReg) ||
10197 !
Attrs.hasAttribute(Attribute::StructRet) || !i->hasStructRetAttr() ||
10198 CLI.CB->getArgOperand(ArgIdx) != i) {
10215 const GlobalValue *GV =
G->getGlobal();
10218 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
TT.isOSBinFormatMachO()))
10238 const AArch64RegisterInfo *
TRI = Subtarget->getRegisterInfo();
10239 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
10241 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
10242 if (Subtarget->hasCustomCallingConv()) {
10243 TRI->UpdateCustomCallPreservedMask(MF, &CallerPreserved);
10244 TRI->UpdateCustomCallPreservedMask(MF, &CalleePreserved);
10246 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
10255 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs,
C);
10259 if (IsVarArg && !(CLI.CB && CLI.CB->isMustTailCall())) {
10267 for (
const CCValAssign &ArgLoc : ArgLocs)
10268 if (!ArgLoc.isRegLoc())
10272 const AArch64FunctionInfo *FuncInfo = MF.
getInfo<AArch64FunctionInfo>();
10280 A.getValVT().isScalableVector() ||
10281 Subtarget->isWindowsArm64EC()) &&
10282 "Expected value to be scalable");
10292 const MachineRegisterInfo &MRI = MF.
getRegInfo();
10299SDValue AArch64TargetLowering::addTokenForArgument(
SDValue Chain,
10302 int ClobberedFI)
const {
10305 int64_t LastByte = FirstByte + MFI.
getObjectSize(ClobberedFI) - 1;
10316 if (FI->getIndex() < 0) {
10318 int64_t InLastByte = InFirstByte;
10321 if ((InFirstByte <= FirstByte && FirstByte <= InLastByte) ||
10322 (FirstByte <= InFirstByte && InFirstByte <= LastByte))
10330bool AArch64TargetLowering::DoesCalleeRestoreStack(
CallingConv::ID CallCC,
10331 bool TailCallOpt)
const {
10339 if (SizeInBits < 8)
10342 APInt RequiredZero(SizeInBits, 0xFE);
10344 bool ZExtBool = (Bits.Zero & RequiredZero) == RequiredZero;
10348void AArch64TargetLowering::AdjustInstrPostInstrSelection(
MachineInstr &
MI,
10354 if (
MI.getOpcode() == AArch64::MSRpstatesvcrImm1 ||
10355 MI.getOpcode() == AArch64::MSRpstatePseudo) {
10356 for (
unsigned I =
MI.getNumOperands() - 1;
I > 0; --
I)
10357 if (MachineOperand &MO =
MI.getOperand(
I);
10358 MO.isReg() && MO.isImplicit() && MO.isDef() &&
10359 (AArch64::GPR32RegClass.contains(MO.getReg()) ||
10360 AArch64::GPR64RegClass.contains(MO.getReg())))
10361 MI.removeOperand(
I);
10365 if (
MI.getOperand(0).getImm() == AArch64SVCR::SVCRSM ||
10366 MI.getOperand(0).getImm() == AArch64SVCR::SVCRSMZA) {
10382 if (MF.
getInfo<AArch64FunctionInfo>()->hasStreamingModeChanges() &&
10383 (
MI.getOpcode() == AArch64::ADDXri ||
10384 MI.getOpcode() == AArch64::SUBXri)) {
10385 const MachineOperand &MO =
MI.getOperand(1);
10394 unsigned Condition,
bool InsertVectorLengthCheck)
const {
10402 Ops.push_back(InGlue);
10403 return DAG.
getNode(AArch64ISD::CHECK_MATCHING_VL,
DL,
10407 if (InsertVectorLengthCheck &&
Enable) {
10410 SDValue CheckVL = GetCheckVL(Chain, InGlue);
10423 assert(PStateReg.
isValid() &&
"PStateSM Register is invalid");
10430 Opcode =
Enable ? AArch64ISD::COND_SMSTART : AArch64ISD::COND_SMSTOP;
10431 Ops.push_back(ConditionOp);
10432 Ops.push_back(PStateSM);
10434 Opcode =
Enable ? AArch64ISD::SMSTART : AArch64ISD::SMSTOP;
10436 Ops.push_back(RegMask);
10439 Ops.push_back(InGlue);
10444 if (!InsertVectorLengthCheck ||
Enable)
10455 if (!
CallAttrs.caller().hasStreamingCompatibleInterface() ||
10458 if (
CallAttrs.callee().hasNonStreamingInterface())
10460 if (
CallAttrs.callee().hasStreamingInterface())
10471 if (Flags.isZExt() || Flags.isSExt())
10478 Arg->
isAssert() ||
Op == AArch64ISD::ASSERT_ZEXT_BOOL) {
10490 int FI = FINode->getIndex();
10506static std::optional<unsigned>
10509 return AArch64ISD::REQUIRES_ZA_SAVE;
10511 return AArch64ISD::REQUIRES_ZT0_SAVE;
10513 return AArch64ISD::INOUT_ZA_USE;
10514 return std::nullopt;
10520AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
10522 SelectionDAG &DAG = CLI.DAG;
10523 SDLoc &
DL = CLI.DL;
10529 bool &IsTailCall = CLI.IsTailCall;
10531 bool IsVarArg = CLI.IsVarArg;
10532 const CallBase *CB = CLI.CB;
10535 MachineFunction::CallSiteInfo CSInfo;
10536 bool IsThisReturn =
false;
10538 AArch64FunctionInfo *FuncInfo = MF.
getInfo<AArch64FunctionInfo>();
10540 bool IsCFICall = CLI.CB && CLI.CB->isIndirectCall() && CLI.CFIType;
10541 bool IsSibCall =
false;
10542 bool GuardWithBTI =
false;
10544 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
10545 !Subtarget->noBTIAtReturnTwice()) {
10551 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.
getContext());
10554 unsigned NumArgs = Outs.
size();
10556 for (
unsigned i = 0; i != NumArgs; ++i) {
10557 if (Outs[i].
Flags.isVarArg() && Outs[i].VT.isScalableVector())
10559 "currently not supported");
10570 RetCCInfo.AnalyzeCallResult(Ins, RetCC);
10578 auto HasSVERegLoc = [](CCValAssign &Loc) {
10579 if (!Loc.isRegLoc())
10581 return AArch64::ZPRRegClass.contains(Loc.getLocReg()) ||
10582 AArch64::PPRRegClass.contains(Loc.getLocReg());
10584 if (
any_of(RVLocs, HasSVERegLoc) ||
any_of(ArgLocs, HasSVERegLoc))
10596 IsTailCall = isEligibleForTailCallOptimization(CLI);
10600 if (!ZAMarkerNode && !TailCallOpt && IsTailCall &&
10608 if (!IsTailCall && CLI.CB && CLI.CB->isMustTailCall())
10610 "site marked musttail");
10627 const Align StackAlign = Subtarget->getFrameLowering()->getStackAlign();
10629 if (IsTailCall && !IsSibCall) {
10635 FPDiff = NumReusableBytes - NumBytes;
10644 NumBytes += Realign;
10648 if (FPDiff < 0 && FuncInfo->getTailCallReservedStack() < (
unsigned)-FPDiff)
10656 assert(FPDiff % 16 == 0 &&
"unaligned stack on tail call");
10659 auto DescribeCallsite =
10660 [&](OptimizationRemarkAnalysis &
R) -> OptimizationRemarkAnalysis & {
10663 R <<
ore::NV(
"Callee", ES->getSymbol());
10664 else if (CLI.CB && CLI.CB->getCalledFunction())
10665 R <<
ore::NV(
"Callee", CLI.CB->getCalledFunction()->getName());
10667 R <<
"unknown callee";
10672 bool RequiresSMChange =
CallAttrs.requiresSMChange();
10673 if (RequiresSMChange) {
10674 OptimizationRemarkEmitter ORE(&MF.
getFunction());
10676 auto R = CLI.CB ? OptimizationRemarkAnalysis(
"sme",
"SMETransition",
10678 : OptimizationRemarkAnalysis(
"sme",
"SMETransition",
10680 DescribeCallsite(R) <<
" requires a streaming mode transition";
10692 !(CLI.CB && CLI.CB->isMustTailCall());
10693 if (IsArm64ECVarArgExitThunk) {
10697 if (Outs.
size() < 2)
10699 "x4/x5 (pointer/length) arguments");
10702 "arm64ec_thunk_x64 calls");
10704 SDValue ThunkVarArgSrc = OutVals[Outs.
size() - 2];
10709 RoundedThunkVarArgSize =
10714 {Chain, RoundedThunkVarArgSize, DAG.getConstant(0, DL, PtrVT)});
10715 Chain = ThunkVarArgDst.
getValue(1);
10723 Chain,
DL, ThunkVarArgDst, ThunkVarArgSrc, ThunkVarArgSize,
Align(16),
10724 Align(1),
false,
false,
10726 MachinePointerInfo());
10731 assert((!IsSibCall || !ZAMarkerNode) &&
"ZA markers require CALLSEQ_START");
10734 if (ZAMarkerNode) {
10741 {Chain, Chain.getValue(1)});
10749 SmallSet<unsigned, 8> RegsUsed;
10752 if (IsVarArg && CLI.CB && CLI.CB->isMustTailCall()) {
10754 for (
const auto &
F : Forwards) {
10761 unsigned ExtraArgLocs = 0;
10762 unsigned NumThunkVarArgOperands = IsArm64ECVarArgExitThunk ? 2 : 0;
10763 for (
unsigned i = 0, e = Outs.
size() - NumThunkVarArgOperands; i != e; ++i) {
10764 CCValAssign &VA = ArgLocs[i - ExtraArgLocs];
10766 ISD::ArgFlagsTy
Flags = Outs[i].Flags;
10781 if (Outs[i].ArgVT == MVT::i1) {
10803 assert(VA.
getValVT() == MVT::i32 &&
"only expect 32 -> 64 upper bits");
10819 assert((isScalable || Subtarget->isWindowsArm64EC()) &&
10820 "Indirect arguments should be scalable on most subtargets");
10823 TypeSize PartSize = StoreSize;
10824 unsigned NumParts = 1;
10825 if (Outs[i].
Flags.isInConsecutiveRegs()) {
10826 while (!Outs[i + NumParts - 1].
Flags.isInConsecutiveRegsLast())
10828 StoreSize *= NumParts;
10837 bool IsPred = VA.
getValVT() == MVT::aarch64svcount ||
10855 if (NumParts > 0) {
10871 if (i == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
10872 Outs[0].VT == MVT::i64) {
10874 "unexpected calling convention register assignment");
10876 "unexpected use of 'returned'");
10877 IsThisReturn =
true;
10886 [=](
const std::pair<unsigned, SDValue> &Elt) {
10895 [&VA](MachineFunction::ArgRegPair ArgReg) {
10896 return ArgReg.Reg == VA.getLocReg();
10903 Arg = DAG.
getNode(AArch64ISD::COALESCER_BARRIER,
DL,
10908 if (
Options.EmitCallSiteInfo)
10910 if (IsArm64ECVarArgExitThunk) {
10914 FPReg = AArch64::D0;
10917 FPReg = AArch64::D1;
10920 FPReg = AArch64::D2;
10923 FPReg = AArch64::D3;
10936 MachinePointerInfo DstInfo;
10940 uint32_t BEAlign = 0;
10946 OpSize =
Flags.isByVal() ?
Flags.getByValSize() * 8
10948 OpSize = (OpSize + 7) / 8;
10949 if (!Subtarget->isLittleEndian() && !
Flags.isByVal() &&
10950 !
Flags.isInConsecutiveRegs()) {
10952 BEAlign = 8 - OpSize;
10955 int32_t
Offset = LocMemOffset + BEAlign;
10972 Chain = addTokenForArgument(Chain, DAG, MF.
getFrameInfo(), FI);
10980 if (Outs[i].
Flags.isByVal()) {
10984 Chain,
DL, DstAddr, Arg, SizeNode,
10985 Outs[i].
Flags.getNonZeroByValAlign(),
10986 Outs[i].Flags.getNonZeroByValAlign(),
10988 nullptr, std::nullopt, DstInfo, MachinePointerInfo());
11005 if (IsVarArg && Subtarget->isWindowsArm64EC() &&
11006 !(CLI.CB && CLI.CB->isMustTailCall()) && !IsArm64ECVarArgExitThunk) {
11024 if (!MemOpChains.
empty())
11028 if (RequiresSMChange) {
11029 bool InsertVectorLengthCheck =
11032 DAG,
DL,
CallAttrs.callee().hasStreamingInterface(), Chain, InGlue,
11039 for (
auto &RegToPass : RegsToPass) {
11041 RegToPass.second, InGlue);
11048 const GlobalValue *CalledGlobal =
nullptr;
11049 unsigned OpFlags = 0;
11051 CalledGlobal =
G->getGlobal();
11052 OpFlags = Subtarget->classifyGlobalFunctionReference(CalledGlobal,
11057 }
else if (!CLI.PAI || !IsTailCall) {
11058 const GlobalValue *GV =
G->getGlobal();
11063 Subtarget->isTargetMachO()) ||
11065 const char *Sym = S->getSymbol();
11078 if (IsTailCall && !IsSibCall) {
11083 unsigned Opc = IsTailCall ? AArch64ISD::TC_RETURN : AArch64ISD::CALL;
11085 std::vector<SDValue>
Ops;
11086 Ops.push_back(Chain);
11087 Ops.push_back(Callee);
11094 "tail calls cannot be marked with clang.arc.attachedcall");
11095 Opc = AArch64ISD::CALL_RVMARKER;
11101 Ops.insert(
Ops.begin() + 1, GA);
11108 Ops.insert(
Ops.begin() + 2, DoEmitMarker);
11110 Opc = AArch64ISD::CALL_ARM64EC_TO_X64;
11111 }
else if (GuardWithBTI) {
11112 Opc = AArch64ISD::CALL_BTI;
11125 "Invalid auth call key");
11129 std::tie(IntDisc, AddrDisc) =
11132 if (
Opc == AArch64ISD::CALL_RVMARKER)
11133 Opc = AArch64ISD::AUTH_CALL_RVMARKER;
11135 Opc = IsTailCall ? AArch64ISD::AUTH_TC_RETURN : AArch64ISD::AUTH_CALL;
11137 Ops.push_back(IntDisc);
11138 Ops.push_back(AddrDisc);
11143 for (
auto &RegToPass : RegsToPass)
11145 RegToPass.second.getValueType()));
11148 const uint32_t *
Mask;
11149 const AArch64RegisterInfo *
TRI = Subtarget->getRegisterInfo();
11150 if (IsThisReturn) {
11152 Mask =
TRI->getThisReturnPreservedMask(MF, CallConv);
11154 IsThisReturn =
false;
11155 Mask =
TRI->getCallPreservedMask(MF, CallConv);
11158 Mask =
TRI->getCallPreservedMask(MF, CallConv);
11160 if (Subtarget->hasCustomCallingConv())
11161 TRI->UpdateCustomCallPreservedMask(MF, &Mask);
11163 if (
TRI->isAnyArgRegReserved(MF))
11164 TRI->emitReservedArgRegCallError(MF);
11166 assert(Mask &&
"Missing call preserved mask for calling convention");
11170 Ops.push_back(InGlue);
11172 if (CLI.DeactivationSymbol)
11181 Ret->
setCFIType(CLI.CFIType->getZExtValue());
11185 if (CalledGlobal &&
11194 Chain->
setCFIType(CLI.CFIType->getZExtValue());
11199 if (CalledGlobal &&
11204 DoesCalleeRestoreStack(CallConv, TailCallOpt) ?
alignTo(NumBytes, 16) : 0;
11212 Chain, InGlue, CallConv, IsVarArg, RVLocs,
DL, DAG, InVals, IsThisReturn,
11213 IsThisReturn ? OutVals[0] :
SDValue(), RequiresSMChange);
11218 if (RequiresSMChange) {
11220 DAG,
DL, !
CallAttrs.callee().hasStreamingInterface(), Result, InGlue,
11224 if (RequiresSMChange) {
11225 for (
unsigned I = 0;
I < InVals.
size(); ++
I) {
11240 for (
const ISD::OutputArg &O : Outs) {
11241 if (
O.Flags.isSwiftSelf() ||
O.Flags.isSwiftError() ||
11242 O.Flags.isSwiftAsync()) {
11246 "Swift attributes can't be used with preserve_none",
11247 DL.getDebugLoc()));
11256bool AArch64TargetLowering::CanLowerReturn(
11259 const Type *RetTy)
const {
11262 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
11273 auto *FuncInfo = MF.
getInfo<AArch64FunctionInfo>();
11277 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, *DAG.
getContext());
11283 SmallSet<unsigned, 4> RegsUsed;
11284 for (
unsigned i = 0, realRVLocIdx = 0; i != RVLocs.
size();
11285 ++i, ++realRVLocIdx) {
11286 CCValAssign &VA = RVLocs[i];
11288 SDValue Arg = OutVals[realRVLocIdx];
11294 if (Outs[i].ArgVT == MVT::i1) {
11310 assert(VA.
getValVT() == MVT::i32 &&
"only expect 32 -> 64 upper bits");
11319 llvm::find_if(RetVals, [=](
const std::pair<unsigned, SDValue> &Elt) {
11329 const AArch64RegisterInfo *
TRI = Subtarget->getRegisterInfo();
11345 for (
auto &RetVal : RetVals) {
11349 DAG.
getNode(AArch64ISD::COALESCER_BARRIER,
DL,
11350 DAG.
getVTList(RetVal.second.getValueType(), MVT::Glue),
11352 Chain = DAG.
getCopyToReg(Chain,
DL, RetVal.first, RetVal.second, Glue);
11355 DAG.
getRegister(RetVal.first, RetVal.second.getValueType()));
11366 unsigned RetValReg = AArch64::X0;
11368 RetValReg = AArch64::X8;
11379 if (AArch64::GPR64RegClass.
contains(*
I))
11381 else if (AArch64::FPR64RegClass.
contains(*
I))
11392 RetOps.push_back(Glue);
11403 MachinePointerInfo());
11404 RetOps.insert(RetOps.begin() + 1, Arm64ECRetDest);
11406 return DAG.
getNode(AArch64ISD::TC_RETURN,
DL, MVT::Other, RetOps);
11409 return DAG.
getNode(AArch64ISD::RET_GLUE,
DL, MVT::Other, RetOps);
11418 unsigned Flag)
const {
11420 N->getOffset(), Flag);
11425 unsigned Flag)
const {
11431 unsigned Flag)
const {
11433 N->getOffset(), Flag);
11438 unsigned Flag)
const {
11444 unsigned Flag)
const {
11449template <
class NodeTy>
11451 unsigned Flags)
const {
11459 .
getInfo<AArch64FunctionInfo>()
11460 ->hasELFSignedGOT())
11463 return DAG.
getNode(AArch64ISD::LOADgot,
DL, Ty, GotAddr);
11467template <
class NodeTy>
11469 unsigned Flags)
const {
11475 AArch64ISD::WrapperLarge,
DL, Ty,
11483template <
class NodeTy>
11485 unsigned Flags)
const {
11493 return DAG.
getNode(AArch64ISD::ADDlow,
DL, Ty, ADRP,
Lo);
11497template <
class NodeTy>
11499 unsigned Flags)
const {
11503 SDValue Sym = getTargetNode(
N, Ty, DAG, Flags);
11504 return DAG.
getNode(AArch64ISD::ADR,
DL, Ty, Sym);
11510 const GlobalValue *GV = GN->
getGlobal();
11511 unsigned OpFlags = Subtarget->ClassifyGlobalReference(GV,
getTargetMachine());
11515 "unexpected offset in global node");
11520 return getGOT(GN, DAG, OpFlags);
11526 Result = getAddrLarge(GN, DAG, OpFlags);
11528 Result = getAddrTiny(GN, DAG, OpFlags);
11530 Result = getAddr(GN, DAG, OpFlags);
11569AArch64TargetLowering::LowerDarwinGlobalTLSAddress(
SDValue Op,
11571 assert(Subtarget->isTargetDarwin() &&
11572 "This function expects a Darwin target");
11587 PtrMemVT,
DL, Chain, DescAddr,
11602 const AArch64RegisterInfo *
TRI = Subtarget->getRegisterInfo();
11603 const uint32_t *
Mask =
TRI->getTLSCallPreservedMask();
11604 if (Subtarget->hasCustomCallingConv())
11613 auto *FuncInfo = MF.
getInfo<AArch64FunctionInfo>();
11616 bool RequiresSMChange = TLSCallAttrs.requiresSMChange();
11618 if (RequiresSMChange)
11623 unsigned Opcode = AArch64ISD::CALL;
11625 Ops.push_back(Chain);
11626 Ops.push_back(FuncTLVGet);
11630 Opcode = AArch64ISD::AUTH_CALL;
11643 {Chain, Chain.getValue(1)});
11645 if (RequiresSMChange)
11761SDValue AArch64TargetLowering::LowerELFTLSDescCallSeq(
SDValue SymAddr,
11766 auto *FuncInfo = MF.
getInfo<AArch64FunctionInfo>();
11770 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
11774 bool RequiresSMChange = TLSCallAttrs.requiresSMChange();
11776 auto ChainAndGlue = [](
SDValue Chain) -> std::pair<SDValue, SDValue> {
11777 return {Chain, Chain.
getValue(1)};
11780 if (RequiresSMChange)
11781 std::tie(Chain, Glue) =
11787 ? AArch64ISD::TLSDESC_AUTH_CALLSEQ
11788 : AArch64ISD::TLSDESC_CALLSEQ;
11790 std::tie(Chain, Glue) = ChainAndGlue(DAG.
getNode(
11794 std::tie(Chain, Glue) = ChainAndGlue(
11795 DAG.
getNode(*ZAMarkerNode,
DL, NodeTys, {Chain, Chain.getValue(1)}));
11797 if (RequiresSMChange)
11798 std::tie(Chain, Glue) =
11806AArch64TargetLowering::LowerELFGlobalTLSAddress(
SDValue Op,
11808 assert(Subtarget->isTargetELF() &&
"This function expects an ELF target");
11811 AArch64FunctionInfo *MFI =
11826 "in local exec TLS model");
11837 const GlobalValue *GV = GA->
getGlobal();
11842 return LowerELFTLSLocalExec(GV, ThreadBase,
DL, DAG);
11845 TPOff = DAG.
getNode(AArch64ISD::LOADgot,
DL, PtrVT, TPOff);
11863 TPOff = LowerELFTLSDescCallSeq(SymAddr,
DL, DAG);
11870 GV,
DL, MVT::i64, 0,
11887 TPOff = LowerELFTLSDescCallSeq(SymAddr,
DL, DAG);
11895AArch64TargetLowering::LowerWindowsGlobalTLSAddress(
SDValue Op,
11897 assert(Subtarget->isTargetWindows() &&
"Windows specific TLS lowering");
11909 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
11922 DAG.
getNode(AArch64ISD::ADDlow,
DL, PtrVT, ADRP, TLSIndexLo);
11923 TLSIndex = DAG.
getLoad(MVT::i32,
DL, Chain, TLSIndex, MachinePointerInfo());
11933 MachinePointerInfo());
11934 Chain =
TLS.getValue(1);
11937 const GlobalValue *GV = GA->
getGlobal();
11949 Addr = DAG.
getNode(AArch64ISD::ADDlow,
DL, PtrVT, Addr, TGALo);
11959 if (Subtarget->isTargetDarwin())
11960 return LowerDarwinGlobalTLSAddress(
Op, DAG);
11961 if (Subtarget->isTargetELF())
11962 return LowerELFGlobalTLSAddress(
Op, DAG);
11963 if (Subtarget->isTargetWindows())
11964 return LowerWindowsGlobalTLSAddress(
Op, DAG);
12002 assert(TGN->getGlobal()->hasExternalWeakLinkage());
12008 if (TGN->getOffset() != 0)
12010 "unsupported non-zero offset in weak ptrauth global reference");
12017 {TGA, Key, Discriminator}),
12022AArch64TargetLowering::LowerPtrAuthGlobalAddress(
SDValue Op,
12025 uint64_t KeyC =
Op.getConstantOperandVal(1);
12026 SDValue AddrDiscriminator =
Op.getOperand(2);
12027 uint64_t DiscriminatorC =
Op.getConstantOperandVal(3);
12028 EVT VT =
Op.getValueType();
12038 "constant discriminator in ptrauth global out of range [0, 0xffff]");
12041 if (!Subtarget->isTargetELF() && !Subtarget->isTargetMachO())
12044 int64_t PtrOffsetC = 0;
12050 const GlobalValue *PtrGV = PtrN->getGlobal();
12053 const unsigned OpFlags =
12057 "unsupported non-GOT op flags on ptrauth global reference");
12060 PtrOffsetC += PtrN->getOffset();
12063 assert(PtrN->getTargetFlags() == 0 &&
12064 "unsupported target flags on ptrauth global");
12069 ? AddrDiscriminator
12073 if (!NeedsGOTLoad) {
12077 {TPtr, Key, TAddrDiscriminator, Discriminator}),
12086 {TPtr, Key, TAddrDiscriminator, Discriminator}),
12114 SDValue Dest,
unsigned Opcode,
12126 uint64_t Mask =
Op.getConstantOperandVal(1);
12131 if (
Op.getOperand(0).getOpcode() ==
ISD::SHL) {
12132 auto Op00 =
Op.getOperand(0).getOperand(0);
12135 Op.getOperand(1),
Op.getOperand(0).getOperand(1));
12136 return DAG.
getNode(Opcode,
DL, MVT::Other, Chain, Shr,
12156 bool ProduceNonFlagSettingCondBr =
12162 if (
LHS.getValueType() == MVT::f128) {
12167 if (!
RHS.getNode()) {
12187 OFCC = getInvertedCondCode(OFCC);
12190 return DAG.
getNode(AArch64ISD::BRCOND,
DL, MVT::Other, Chain, Dest, CCVal,
12197 using namespace llvm::SDPatternMatch;
12209 return DAG.
getNode(AArch64ISD::BRCOND,
DL, MVT::Other, Chain, Dest,
12214 if (
LHS.getValueType().isInteger()) {
12216 (
LHS.getValueType() == MVT::i32 ||
LHS.getValueType() == MVT::i64));
12221 if (RHSC && RHSC->
getZExtValue() == 1 && ProduceNonFlagSettingCondBr &&
12225 LHS.getResNo() == 0 &&
12229 bool CanNegate, MustBeFirst, PreferFirst;
12262 if (RHSC && RHSC->
getZExtValue() == 0 && ProduceNonFlagSettingCondBr) {
12268 return DAG.
getNode(AArch64ISD::CBZ,
DL, MVT::Other, Chain,
LHS, Dest);
12274 return DAG.
getNode(AArch64ISD::CBNZ,
DL, MVT::Other, Chain,
LHS, Dest);
12281 return DAG.
getNode(AArch64ISD::TBNZ,
DL, MVT::Other, Chain,
LHS,
12286 LHS.getOpcode() !=
ISD::AND && ProduceNonFlagSettingCondBr) {
12292 return DAG.
getNode(AArch64ISD::TBZ,
DL, MVT::Other, Chain,
LHS,
12298 if (Subtarget->hasCMPBR() &&
12300 ProduceNonFlagSettingCondBr) {
12309 return DAG.
getNode(AArch64ISD::BRCOND,
DL, MVT::Other, Chain, Dest, CCVal,
12313 assert(
LHS.getValueType() == MVT::f16 ||
LHS.getValueType() == MVT::bf16 ||
12314 LHS.getValueType() == MVT::f32 ||
LHS.getValueType() == MVT::f64);
12323 DAG.
getNode(AArch64ISD::BRCOND,
DL, MVT::Other, Chain, Dest, CC1Val, Cmp);
12326 return DAG.
getNode(AArch64ISD::BRCOND,
DL, MVT::Other, BR1, Dest, CC2Val,
12335 if (!Subtarget->isNeonAvailable() &&
12336 !Subtarget->useSVEForFixedLengthVectors())
12339 EVT VT =
Op.getValueType();
12367 if (!VT.
isVector() && !Subtarget->isNeonAvailable() &&
12368 Subtarget->isSVEorStreamingSVEAvailable()) {
12369 if (VT != MVT::f16 && VT != MVT::f32 && VT != MVT::f64 && VT != MVT::bf16)
12383 auto BitCast = [
this](EVT VT,
SDValue Op, SelectionDAG &DAG) {
12385 return getSVESafeBitCast(VT,
Op, DAG);
12392 auto SetVecVal = [&](
int Idx = -1) {
12398 VecVal1 = BitCast(VecVT, In1, DAG);
12399 VecVal2 = BitCast(VecVT, In2, DAG);
12405 }
else if (VT == MVT::f64) {
12406 VecVT = MVT::v2i64;
12407 SetVecVal(AArch64::dsub);
12408 }
else if (VT == MVT::f32) {
12409 VecVT = MVT::v4i32;
12410 SetVecVal(AArch64::ssub);
12411 }
else if (VT == MVT::f16 || VT == MVT::bf16) {
12412 VecVT = MVT::v8i16;
12413 SetVecVal(AArch64::hsub);
12424 if (VT == MVT::f64 || VT == MVT::v2f64) {
12432 DAG.
getNode(AArch64ISD::BSP,
DL, VecVT, SignMaskV, VecVal1, VecVal2);
12433 if (VT == MVT::f16 || VT == MVT::bf16)
12435 if (VT == MVT::f32)
12437 if (VT == MVT::f64)
12440 return BitCast(VT, BSP, DAG);
12446 Attribute::NoImplicitFloat))
12449 EVT VT =
Op.getValueType();
12450 if (VT.
isVector() && Subtarget->isSVEorStreamingSVEAvailable())
12451 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::CTPOP_MERGE_PASSTHRU);
12459 if (VT == MVT::i32 && IsParity)
12462 if (Subtarget->isSVEorStreamingSVEAvailable()) {
12463 if (VT == MVT::i32 || VT == MVT::i64) {
12464 EVT ContainerVT = VT == MVT::i32 ? MVT::nxv4i32 : MVT::nxv2i64;
12476 if (VT == MVT::i128) {
12489 if (!Subtarget->isNeonAvailable())
12500 if (VT == MVT::i32 || VT == MVT::i64) {
12501 if (VT == MVT::i32)
12507 AddV = DAG.
getNode(AArch64ISD::NVCAST,
DL,
12508 VT == MVT::i32 ? MVT::v2i32 : MVT::v1i64, AddV);
12514 }
else if (VT == MVT::i128) {
12520 DAG.
getNode(AArch64ISD::NVCAST,
DL, MVT::v2i64, AddV),
12528 assert(!IsParity &&
"ISD::PARITY of vector types not supported");
12530 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
12531 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
12532 "Unexpected type for custom ctpop lowering");
12540 EVT DT = VT == MVT::v2i64 ? MVT::v4i32 : VT;
12544 if (VT == MVT::v2i64) {
12545 Val = DAG.
getNode(AArch64ISD::UDOT,
DL, DT, Zeros, Ones, Val);
12546 Val = DAG.
getNode(AArch64ISD::UADDLP,
DL, VT, Val);
12547 }
else if (VT == MVT::v2i32) {
12548 Val = DAG.
getNode(AArch64ISD::UDOT,
DL, DT, Zeros, Ones, Val);
12549 }
else if (VT == MVT::v4i32) {
12550 Val = DAG.
getNode(AArch64ISD::UDOT,
DL, DT, Zeros, Ones, Val);
12559 unsigned EltSize = 8;
12565 Val = DAG.
getNode(AArch64ISD::UADDLP,
DL, WidenVT, Val);
12572 EVT VT =
Op.getValueType();
12581 EVT VT =
Op.getValueType();
12583 unsigned Opcode =
Op.getOpcode();
12604 if (VT.
isVector() && Subtarget->isSVEorStreamingSVEAvailable()) {
12609 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::SMAX_PRED);
12611 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::SMIN_PRED);
12613 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::UMAX_PRED);
12615 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::UMIN_PRED);
12627 EVT VT =
Op.getValueType();
12629 if (Subtarget->isSVEorStreamingSVEAvailable())
12630 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::BITREVERSE_MERGE_PASSTHRU);
12642 REVB = DAG.
getNode(AArch64ISD::REV32,
DL, VST,
Op.getOperand(0));
12649 REVB = DAG.
getNode(AArch64ISD::REV32,
DL, VST,
Op.getOperand(0));
12656 REVB = DAG.
getNode(AArch64ISD::REV64,
DL, VST,
Op.getOperand(0));
12663 REVB = DAG.
getNode(AArch64ISD::REV64,
DL, VST,
Op.getOperand(0));
12669 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT,
12676 return Imm.sgt(-32) &&
Imm.slt(32);
12708 const std::pair<SDValue, SDValue> &Pair) {
12709 for (
SDValue V : {Pair.first, Pair.second}) {
12714 unsigned BitWidth =
Imm.getBitWidth() <= 32 ? 32 : 64;
12725 unsigned &NumXors,
bool &SawXor,
bool RequireLegalCmpImmediates,
12732 N =
N->getOperand(0);
12735 if (RequireLegalCmpImmediates &&
12738 WorkList.push_back(std::make_pair(
N->getOperand(0),
N->getOperand(1)));
12746 if (
N->getOpcode() ==
ISD::OR &&
N->hasOneUse())
12747 return isOrXorChain(
N->getOperand(0), DAG, NumLeaves, NumXors, SawXor,
12748 RequireLegalCmpImmediates, WorkList) &&
12749 isOrXorChain(
N->getOperand(1), DAG, NumLeaves, NumXors, SawXor,
12750 RequireLegalCmpImmediates, WorkList);
12754 EVT VT =
N.getValueType();
12772 EVT VT =
N->getValueType(0);
12776 if (
N->getOpcode() !=
ISD::SETCC ||
LHS.getValueType().isVector() ||
12777 LHS.getValueType().getSizeInBits() > 64)
12783 unsigned NumLeaves = 0;
12784 unsigned NumXors = 0;
12785 bool SawXor =
false;
12787 return User->getOpcode() == ISD::BRCOND ||
12788 User->getOpcode() == AArch64ISD::BRCOND;
12793 RequireLegalCmpImmediates, WorkList) &&
12800 unsigned Limit = 5;
12801 if (NumXors >= 6) {
12803 if (NumXors == NumLeaves)
12804 Limit = std::min<unsigned>(8, NumXors);
12806 if (
F.hasMinSize())
12808 if (WorkList.
size() > Limit)
12811 if (WorkList.
size() > 2 &&
12818 auto PreferAsFirstCmp = [](
const std::pair<SDValue, SDValue> &Pair) {
12823 find_if(WorkList, PreferAsFirstCmp);
12828 std::tie(XOR0, XOR1) = WorkList[0];
12831 for (
unsigned I = 1;
I < WorkList.
size();
I++) {
12832 std::tie(XOR0, XOR1) = WorkList[
I];
12834 Cmp = DAG.
getNode(LogicOp,
DL, VT, Cmp, CmpChain);
12846 if (
Op.getValueType().isVector())
12847 return LowerVSETCC(
Op, DAG);
12849 bool IsStrict =
Op->isStrictFPOpcode();
12851 unsigned OpNo = IsStrict ? 1 : 0;
12854 Chain =
Op.getOperand(0);
12861 EVT VT =
Op.getValueType();
12867 if (
LHS.getValueType() == MVT::f128) {
12872 if (!
RHS.getNode()) {
12873 assert(
LHS.getValueType() ==
Op.getValueType() &&
12874 "Unexpected setcc expansion!");
12879 if (
LHS.getValueType().isInteger()) {
12895 SDValue Res = DAG.
getNode(AArch64ISD::CSEL,
DL, VT, FVal, TVal, CCVal, Cmp);
12900 assert(
LHS.getValueType() == MVT::bf16 ||
LHS.getValueType() == MVT::f16 ||
12901 LHS.getValueType() == MVT::f32 ||
LHS.getValueType() == MVT::f64);
12922 Res = DAG.
getNode(AArch64ISD::CSEL,
DL, VT, FVal, TVal, CC1Val, Cmp);
12932 DAG.
getNode(AArch64ISD::CSEL,
DL, VT, TVal, FVal, CC1Val, Cmp);
12935 Res = DAG.
getNode(AArch64ISD::CSEL,
DL, VT, TVal, CS1, CC2Val, Cmp);
12945 EVT VT =
LHS.getValueType();
12946 if (VT != MVT::i32 && VT != MVT::i64)
12956 EVT OpVT =
Op.getValueType();
12965 return DAG.
getNode(AArch64ISD::CSEL,
DL, OpVT, FVal, TVal, CCVal,
12974 "function only supposed to emit natural comparisons");
12983 if (!
LHS.getValueType().isVector()) {
13022 assert(!
LHS.getValueType().isVector());
13023 assert(!
RHS.getValueType().isVector());
13027 if (!CTVal || !CFVal)
13041 bool OneNaN =
false;
13057 bool ShouldInvert =
false;
13066 if (!Cmp2 && !ShouldInvert)
13083SDValue AArch64TargetLowering::LowerSELECT_CC(
13089 if (
LHS.getValueType() == MVT::f128) {
13094 if (!
RHS.getNode()) {
13101 if ((
LHS.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) ||
13102 LHS.getValueType() == MVT::bf16) {
13108 if (
LHS.getValueType().isInteger()) {
13110 (
LHS.getValueType() == MVT::i32 ||
LHS.getValueType() == MVT::i64));
13122 LHS.getValueType() ==
RHS.getValueType()) {
13123 EVT VT =
LHS.getValueType();
13129 Shift = DAG.
getNOT(
DL, Shift, VT);
13145 EVT TestVT =
LHS.getValueType();
13149 LHS, SignBitConst);
13177 unsigned Opcode = AArch64ISD::CSEL;
13185 }
else if (CTVal && CFVal && CTVal->
isOne() && CFVal->
isZero()) {
13205 }
else if (CTVal && CFVal) {
13213 if (TrueVal == ~FalseVal) {
13214 Opcode = AArch64ISD::CSINV;
13215 }
else if (FalseVal > std::numeric_limits<int64_t>::min() &&
13216 TrueVal == -FalseVal) {
13217 Opcode = AArch64ISD::CSNEG;
13227 if ((TrueVal32 == FalseVal32 + 1) || (TrueVal32 + 1 == FalseVal32)) {
13228 Opcode = AArch64ISD::CSINC;
13230 if (TrueVal32 > FalseVal32) {
13239 if ((TrueVal64 == FalseVal64 + 1) || (TrueVal64 + 1 == FalseVal64)) {
13240 Opcode = AArch64ISD::CSINC;
13242 if (TrueVal > FalseVal) {
13255 if (Opcode != AArch64ISD::CSEL) {
13268 if (Opcode == AArch64ISD::CSEL && RHSVal && !RHSVal->
isOne() &&
13273 if (CTVal && CTVal == RHSVal && AArch64CC ==
AArch64CC::EQ)
13275 else if (CFVal && CFVal == RHSVal && AArch64CC ==
AArch64CC::NE)
13277 }
else if (Opcode == AArch64ISD::CSNEG && RHSVal && RHSVal->
isOne()) {
13278 assert (CTVal && CFVal &&
"Expected constant operands for CSNEG.");
13283 Opcode = AArch64ISD::CSINV;
13292 return DAG.
getNode(Opcode,
DL, VT, TVal, FVal, CCVal, Cmp);
13296 assert(
LHS.getValueType() == MVT::f16 ||
LHS.getValueType() == MVT::f32 ||
13297 LHS.getValueType() == MVT::f64);
13304 if (Subtarget->isNeonAvailable() &&
all_of(
Users, [](
const SDNode *U) {
13305 switch (
U->getOpcode()) {
13310 case AArch64ISD::DUP:
13328 if (
Flags.hasNoSignedZeros()) {
13332 if (RHSVal && RHSVal->
isZero()) {
13340 CFVal && CFVal->
isZero() &&
13356 return DAG.
getNode(AArch64ISD::CSEL,
DL, VT, TVal, CS1, CC2Val, Cmp);
13365 EVT Ty =
Op.getValueType();
13368 auto Idx =
Op.getConstantOperandAPInt(2);
13369 int64_t IdxVal = Idx.getSExtValue();
13371 "Only expect scalable vectors for custom lowering of VECTOR_SPLICE");
13380 std::optional<unsigned> PredPattern;
13392 return DAG.
getNode(AArch64ISD::SPLICE,
DL, Ty, Pred,
Op.getOperand(0),
13412 SDNodeFlags
Flags =
Op->getFlags();
13414 return LowerSELECT_CC(CC,
LHS,
RHS, TVal, FVal,
Op->users(), Flags,
DL, DAG);
13424 EVT Ty =
Op.getValueType();
13425 if (Ty == MVT::aarch64svcount) {
13462 return DAG.
getNode(AArch64ISD::CSEL,
DL,
Op.getValueType(), TVal, FVal,
13481 if ((Ty == MVT::f16 || Ty == MVT::bf16) && !Subtarget->hasFullFP16()) {
13488 Op->getFlags(),
DL, DAG);
13490 if ((Ty == MVT::f16 || Ty == MVT::bf16) && !Subtarget->hasFullFP16()) {
13505 !Subtarget->isTargetMachO())
13506 return getAddrLarge(JT, DAG);
13508 return getAddrTiny(JT, DAG);
13509 return getAddr(JT, DAG);
13522 AFI->setJumpTableEntryInfo(JTI, 4,
nullptr);
13527 "aarch64-jump-table-hardening")) {
13529 if (Subtarget->isTargetMachO()) {
13534 assert(Subtarget->isTargetELF() &&
13535 "jump table hardening only supported on MachO/ELF");
13566 std::optional<uint16_t> BADisc =
13567 Subtarget->getPtrAuthBlockAddressDiscriminatorIfEnabled(MF.
getFunction());
13578 {Dest,
Key, Disc, AddrDisc, Chain});
13588 if (Subtarget->isTargetMachO()) {
13589 return getGOT(CP, DAG);
13592 return getAddrLarge(CP, DAG);
13594 return getAddrTiny(CP, DAG);
13596 return getAddr(CP, DAG);
13604 if (std::optional<uint16_t> BADisc =
13605 Subtarget->getPtrAuthBlockAddressDiscriminatorIfEnabled(
13619 {TargetBA,
Key, AddrDisc, Disc});
13627 return getAddrLarge(BAN, DAG);
13629 return getAddrTiny(BAN, DAG);
13631 return getAddr(BAN, DAG);
13636 AArch64FunctionInfo *FuncInfo =
13645 MachinePointerInfo(SV));
13651 AArch64FunctionInfo *FuncInfo = MF.
getInfo<AArch64FunctionInfo>();
13655 if (Subtarget->isWindowsArm64EC()) {
13676 MachinePointerInfo(SV));
13684 AArch64FunctionInfo *FuncInfo = MF.
getInfo<AArch64FunctionInfo>();
13685 unsigned PtrSize = Subtarget->isTargetILP32() ? 4 : 8;
13700 MachinePointerInfo(SV),
Align(PtrSize)));
13717 MachinePointerInfo(SV,
Offset),
13735 MachinePointerInfo(SV,
Offset),
13745 GROffsAddr, MachinePointerInfo(SV,
Offset),
Align(4)));
13753 VROffsAddr, MachinePointerInfo(SV,
Offset),
Align(4)));
13763 if (Subtarget->isCallingConvWin64(
F.getCallingConv(),
F.isVarArg()))
13764 return LowerWin64_VASTART(
Op, DAG);
13765 else if (Subtarget->isTargetDarwin())
13766 return LowerDarwin_VASTART(
Op, DAG);
13768 return LowerAAPCS_VASTART(
Op, DAG);
13776 unsigned PtrSize = Subtarget->isTargetILP32() ? 4 : 8;
13777 unsigned VaListSize =
13778 (Subtarget->isTargetDarwin() || Subtarget->isTargetWindows())
13780 : Subtarget->isTargetILP32() ? 20 : 32;
13786 Align(PtrSize),
Align(PtrSize),
false,
false,
13787 nullptr, std::nullopt, MachinePointerInfo(DestSV),
13788 MachinePointerInfo(SrcSV));
13792 assert(Subtarget->isTargetDarwin() &&
13793 "automatic va_arg instruction only works on Darwin");
13796 EVT VT =
Op.getValueType();
13800 MaybeAlign
Align(
Op.getConstantOperandVal(3));
13801 unsigned MinSlotSize = Subtarget->isTargetILP32() ? 4 : 8;
13805 DAG.
getLoad(PtrMemVT,
DL, Chain, Addr, MachinePointerInfo(V));
13811 "currently not supported");
13813 if (Align && *Align > MinSlotSize) {
13829 ArgSize = std::max(ArgSize, MinSlotSize);
13830 bool NeedFPTrunc =
false;
13833 NeedFPTrunc =
true;
13843 DAG.
getStore(Chain,
DL, VANext, Addr, MachinePointerInfo(V));
13849 DAG.
getLoad(MVT::f64,
DL, APStore, VAList, MachinePointerInfo());
13859 return DAG.
getLoad(VT,
DL, APStore, VAList, MachinePointerInfo());
13867 EVT VT =
Op.getValueType();
13869 unsigned Depth =
Op.getConstantOperandVal(0);
13874 MachinePointerInfo());
13876 if (Subtarget->isTargetILP32())
13892#define GET_REGISTER_MATCHER
13893#include "AArch64GenAsmMatcher.inc"
13918 EVT VT =
Op.getValueType();
13934 EVT VT =
Op.getValueType();
13936 unsigned Depth =
Op.getConstantOperandVal(0);
13939 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
13956 if (Subtarget->hasPAuth()) {
13993 const APInt ImmInt =
Imm.bitcastToAPInt();
13995 if (VT == MVT::f64)
13998 if (VT == MVT::f32)
14001 if (VT == MVT::f16 || VT == MVT::bf16)
14009 bool OptForSize)
const {
14017 if (!IsLegal && (VT == MVT::f64 || VT == MVT::f32)) {
14025 const APInt ImmInt =
Imm.bitcastToAPInt();
14028 "Should be able to build any value with at most 4 moves");
14030 unsigned Limit = OptForSize ? 1 : 2;
14032 if (!OptForSize && Insn.
size() > Limit && Subtarget->hasFuseLiterals()) {
14034 for (
unsigned I = 0;
I + 1 < Insn.
size(); ++
I) {
14047 IsLegal = Insn.
size() <= Limit;
14064 if ((ST->hasNEON() &&
14065 (VT == MVT::f64 || VT == MVT::v1f64 || VT == MVT::v2f64 ||
14066 VT == MVT::f32 || VT == MVT::v1f32 || VT == MVT::v2f32 ||
14067 VT == MVT::v4f32)) ||
14069 (VT == MVT::nxv8f16 || VT == MVT::nxv4f32 || VT == MVT::nxv2f64))) {
14076 constexpr unsigned AccurateBits = 8;
14078 ExtraSteps = DesiredBits <= AccurateBits
14083 return DAG.
getNode(Opcode,
SDLoc(Operand), VT, Operand);
14093 EVT VT =
Op.getValueType();
14101AArch64TargetLowering::getSqrtResultForDenormInput(
SDValue Op,
14110 bool Reciprocal)
const {
14114 DAG, ExtraSteps)) {
14119 SDNodeFlags
Flags =
14124 for (
int i = ExtraSteps; i > 0; --i) {
14127 Step = DAG.
getNode(AArch64ISD::FRSQRTS,
DL, VT, Operand, Step, Flags);
14142 int &ExtraSteps)
const {
14145 DAG, ExtraSteps)) {
14153 for (
int i = ExtraSteps; i > 0; --i) {
14193const char *AArch64TargetLowering::LowerXConstraint(
EVT ConstraintVT)
const {
14201 if (!Subtarget->hasFPARMv8())
14226static std::optional<std::pair<unsigned, const TargetRegisterClass *>>
14229 (Constraint[1] !=
'p' && Constraint[1] !=
'z'))
14230 return std::nullopt;
14232 bool IsPredicate = Constraint[1] ==
'p';
14233 Constraint = Constraint.
substr(2, Constraint.
size() - 3);
14234 bool IsPredicateAsCount = IsPredicate && Constraint.
starts_with(
"n");
14235 if (IsPredicateAsCount)
14240 return std::nullopt;
14242 if (IsPredicateAsCount)
14243 return std::make_pair(AArch64::PN0 + V, &AArch64::PNRRegClass);
14245 return std::make_pair(AArch64::P0 + V, &AArch64::PPRRegClass);
14246 return std::make_pair(AArch64::Z0 + V, &AArch64::ZPRRegClass);
14249static std::optional<PredicateConstraint>
14263 switch (Constraint) {
14265 return VT == MVT::aarch64svcount ? &AArch64::PNR_p8to15RegClass
14266 : &AArch64::PPR_p8to15RegClass;
14268 return VT == MVT::aarch64svcount ? &AArch64::PNR_3bRegClass
14269 : &AArch64::PPR_3bRegClass;
14271 return VT == MVT::aarch64svcount ? &AArch64::PNRRegClass
14272 : &AArch64::PPRRegClass;
14280static std::optional<ReducedGprConstraint>
14293 switch (Constraint) {
14295 return &AArch64::MatrixIndexGPR32_8_11RegClass;
14297 return &AArch64::MatrixIndexGPR32_12_15RegClass;
14331 return DAG.
getNode(AArch64ISD::CSINC,
DL, MVT::i32,
14334 getCondCode(DAG, getInvertedCondCode(CC)), NZCV);
14338SDValue AArch64TargetLowering::LowerAsmOutputForConstraint(
14340 const AsmOperandInfo &OpInfo,
SelectionDAG &DAG)
const {
14345 if (OpInfo.ConstraintVT.isVector() || !OpInfo.ConstraintVT.isInteger() ||
14346 OpInfo.ConstraintVT.getSizeInBits() < 8)
14361 if (OpInfo.ConstraintVT.getSizeInBits() <= 32)
14372AArch64TargetLowering::getConstraintType(
StringRef Constraint)
const {
14373 if (Constraint.
size() == 1) {
14374 switch (Constraint[0]) {
14411AArch64TargetLowering::getSingleConstraintMatchWeight(
14412 AsmOperandInfo &
info,
const char *constraint)
const {
14414 Value *CallOperandVal =
info.CallOperandVal;
14417 if (!CallOperandVal)
14421 switch (*constraint) {
14443std::pair<unsigned, const TargetRegisterClass *>
14444AArch64TargetLowering::getRegForInlineAsmConstraint(
14446 if (Constraint.
size() == 1) {
14447 switch (Constraint[0]) {
14450 return std::make_pair(0U,
nullptr);
14452 return std::make_pair(0U, &AArch64::GPR64x8ClassRegClass);
14454 return std::make_pair(0U, &AArch64::GPR64commonRegClass);
14455 return std::make_pair(0U, &AArch64::GPR32commonRegClass);
14457 if (!Subtarget->hasFPARMv8())
14461 return std::make_pair(0U, &AArch64::ZPRRegClass);
14462 return std::make_pair(0U,
nullptr);
14464 if (VT == MVT::Other)
14468 return std::make_pair(0U, &AArch64::FPR16RegClass);
14470 return std::make_pair(0U, &AArch64::FPR32RegClass);
14472 return std::make_pair(0U, &AArch64::FPR64RegClass);
14474 return std::make_pair(0U, &AArch64::FPR128RegClass);
14480 if (!Subtarget->hasFPARMv8())
14483 return std::make_pair(0U, &AArch64::ZPR_4bRegClass);
14485 return std::make_pair(0U, &AArch64::FPR128_loRegClass);
14488 if (!Subtarget->hasFPARMv8())
14491 return std::make_pair(0U, &AArch64::ZPR_3bRegClass);
14496 if (!AArch64::ZPRRegClass.hasSubClassEq(
P->second))
14501 if (VT == MVT::Other) {
14505 if (!Subtarget->isSVEorStreamingSVEAvailable())
14506 return std::make_pair(
TRI->getSubReg(
P->first, AArch64::zsub),
14507 &AArch64::FPR128RegClass);
14511 if (Subtarget->isSVEorStreamingSVEAvailable()) {
14521 case MVT::nxv8bf16:
14528 return std::make_pair(0U,
nullptr);
14532 return std::make_pair(0U, RegClass);
14536 return std::make_pair(0U, RegClass);
14538 if (StringRef(
"{cc}").equals_insensitive(Constraint) ||
14540 return std::make_pair(
unsigned(AArch64::NZCV), &AArch64::CCRRegClass);
14542 if (Constraint ==
"{za}") {
14543 return std::make_pair(
unsigned(AArch64::ZA), &AArch64::MPRRegClass);
14546 if (Constraint ==
"{zt0}") {
14547 return std::make_pair(
unsigned(AArch64::ZT0), &AArch64::ZTRRegClass);
14557 unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.
lower())
14558 .Cases({
"{x29}",
"{fp}"}, AArch64::FP)
14559 .Cases({
"{x30}",
"{lr}"}, AArch64::LR)
14560 .
Default(AArch64::NoRegister);
14561 if (XRegFromAlias != AArch64::NoRegister)
14562 return std::make_pair(XRegFromAlias, &AArch64::GPR64RegClass);
14566 std::pair<unsigned, const TargetRegisterClass *> Res;
14571 unsigned Size = Constraint.
size();
14572 if ((
Size == 4 ||
Size == 5) && Constraint[0] ==
'{' &&
14573 tolower(Constraint[1]) ==
'v' && Constraint[
Size - 1] ==
'}') {
14576 if (!
Failed && RegNo >= 0 && RegNo <= 31) {
14580 if (VT != MVT::Other) {
14583 Res.first = AArch64::FPR16RegClass.getRegister(RegNo);
14584 Res.second = &AArch64::FPR16RegClass;
14587 Res.first = AArch64::FPR32RegClass.getRegister(RegNo);
14588 Res.second = &AArch64::FPR32RegClass;
14591 Res.first = AArch64::FPR64RegClass.getRegister(RegNo);
14592 Res.second = &AArch64::FPR64RegClass;
14595 Res.first = AArch64::FPR128RegClass.getRegister(RegNo);
14596 Res.second = &AArch64::FPR128RegClass;
14599 return std::make_pair(0U,
nullptr);
14602 Res.first = AArch64::FPR128RegClass.getRegister(RegNo);
14603 Res.second = &AArch64::FPR128RegClass;
14609 if (Res.second && !Subtarget->hasFPARMv8() &&
14610 !AArch64::GPR32allRegClass.hasSubClassEq(Res.second) &&
14611 !AArch64::GPR64allRegClass.hasSubClassEq(Res.second))
14612 return std::make_pair(0U,
nullptr);
14619 bool AllowUnknown)
const {
14620 if (Subtarget->hasLS64() && Ty->isIntegerTy(512))
14621 return EVT(MVT::i64x8);
14628void AArch64TargetLowering::LowerAsmOperandForConstraint(
14634 if (Constraint.
size() != 1)
14637 char ConstraintLetter = Constraint[0];
14638 switch (ConstraintLetter) {
14649 if (
Op.getValueType() == MVT::i64)
14650 Result = DAG.
getRegister(AArch64::XZR, MVT::i64);
14652 Result = DAG.
getRegister(AArch64::WZR, MVT::i32);
14674 switch (ConstraintLetter) {
14688 CVal =
C->getSExtValue();
14719 if ((CVal & 0xFFFF) == CVal)
14721 if ((CVal & 0xFFFF0000ULL) == CVal)
14724 if ((NCVal & 0xFFFFULL) == NCVal)
14726 if ((NCVal & 0xFFFF0000ULL) == NCVal)
14733 if ((CVal & 0xFFFFULL) == CVal)
14735 if ((CVal & 0xFFFF0000ULL) == CVal)
14737 if ((CVal & 0xFFFF00000000ULL) == CVal)
14739 if ((CVal & 0xFFFF000000000000ULL) == CVal)
14742 if ((NCVal & 0xFFFFULL) == NCVal)
14744 if ((NCVal & 0xFFFF0000ULL) == NCVal)
14746 if ((NCVal & 0xFFFF00000000ULL) == NCVal)
14748 if ((NCVal & 0xFFFF000000000000ULL) == NCVal)
14762 Ops.push_back(Result);
14798 EVT VT =
Op.getValueType();
14800 "Scalable vectors cannot be used with ISD::BUILD_VECTOR");
14804 if (VT != MVT::v16i8 && VT != MVT::v8i8)
14808 assert((NumElts == 8 || NumElts == 16) &&
14809 "Need to have exactly 8 or 16 elements in vector.");
14815 for (
unsigned i = 0; i < NumElts; ++i) {
14822 SourceVec = OperandSourceVec;
14823 else if (SourceVec != OperandSourceVec)
14836 }
else if (!AndMaskConstants.
empty()) {
14856 if (!MaskSourceVec) {
14860 }
else if (MaskSourceVec != MaskSource->
getOperand(0)) {
14874 if (!AndMaskConstants.
empty())
14881 SourceVec, MaskSourceVec);
14889 LLVM_DEBUG(
dbgs() <<
"AArch64TargetLowering::ReconstructShuffle\n");
14891 EVT VT =
Op.getValueType();
14893 "Scalable vectors cannot be used with ISD::BUILD_VECTOR");
14896 struct ShuffleSourceInfo {
14911 ShuffleSourceInfo(
SDValue Vec)
14912 : Vec(Vec), MinElt(std::numeric_limits<unsigned>::max()), MaxElt(0),
14913 ShuffleVec(Vec), WindowBase(0), WindowScale(1) {}
14918 auto IsNeonSized = [](
EVT VT) {
14925 for (
unsigned i = 0; i < NumElts; ++i) {
14931 !IsNeonSized(V->getOperand(0).getValueType())) {
14933 dbgs() <<
"Reshuffle failed: "
14934 "a shuffle can only come from building a vector from "
14935 "various elements of other NEON-sized vectors, provided "
14936 "their indices are constant\n");
14942 auto Source =
find(Sources, SourceVec);
14943 if (Source == Sources.
end())
14944 Source = Sources.
insert(Sources.
end(), ShuffleSourceInfo(SourceVec));
14947 unsigned EltNo = V.getConstantOperandVal(1);
14948 Source->MinElt = std::min(Source->MinElt, EltNo);
14949 Source->MaxElt = std::max(Source->MaxElt, EltNo);
14954 if ((Sources.
size() == 3 || Sources.
size() == 4) && NumElts > 4) {
14959 for (
unsigned I = 0;
I < NumElts; ++
I) {
14962 for (
unsigned OF = 0; OF < OutputFactor; OF++)
14963 Mask.push_back(-1);
14969 unsigned Lane = V.getConstantOperandVal(1);
14970 for (
unsigned S = 0; S < Sources.
size(); S++) {
14971 if (V.getOperand(0) == Sources[S].Vec) {
14972 unsigned InputSize = Sources[S].Vec.getScalarValueSizeInBits();
14973 unsigned InputBase = 16 * S + Lane * InputSize / 8;
14974 for (
unsigned OF = 0; OF < OutputFactor; OF++)
14975 Mask.push_back(InputBase + OF);
14985 ? Intrinsic::aarch64_neon_tbl3
14986 : Intrinsic::aarch64_neon_tbl4,
14988 for (
unsigned i = 0; i < Sources.
size(); i++) {
14989 SDValue Src = Sources[i].Vec;
14990 EVT SrcVT = Src.getValueType();
14993 "Expected a legally typed vector");
15001 for (
unsigned i = 0; i < Mask.size(); i++)
15003 assert((Mask.size() == 8 || Mask.size() == 16) &&
15004 "Expected a v8i8 or v16i8 Mask");
15006 Mask.size() == 8 ? MVT::v8i8 : MVT::v16i8,
DL, TBLMask));
15010 Mask.size() == 8 ? MVT::v8i8 : MVT::v16i8, TBLOperands);
15014 if (Sources.
size() > 2) {
15015 LLVM_DEBUG(
dbgs() <<
"Reshuffle failed: currently only do something "
15016 <<
"sensible when at most two source vectors are "
15024 for (
auto &Source : Sources) {
15025 EVT SrcEltTy = Source.Vec.getValueType().getVectorElementType();
15026 if (SrcEltTy.
bitsLT(SmallestEltTy)) {
15027 SmallestEltTy = SrcEltTy;
15030 unsigned ResMultiplier =
15039 for (
auto &Src : Sources) {
15040 EVT SrcVT = Src.ShuffleVec.getValueType();
15053 assert(2 * SrcVTSize == VTSize);
15058 DAG.
getPOISON(Src.ShuffleVec.getValueType()));
15064 dbgs() <<
"Reshuffle failed: result vector too small to extract\n");
15068 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
15070 dbgs() <<
"Reshuffle failed: span too large for a VEXT to cope\n");
15074 if (Src.MinElt >= NumSrcElts) {
15078 Src.WindowBase = -NumSrcElts;
15079 }
else if (Src.MaxElt < NumSrcElts) {
15091 dbgs() <<
"Reshuffle failed: don't know how to lower AArch64ISD::EXT "
15092 "for SVE vectors.");
15097 DAG.
getNode(AArch64ISD::EXT,
DL, DestVT, VEXTSrc1, VEXTSrc2,
15099 Src.WindowBase = -Src.MinElt;
15106 for (
auto &Src : Sources) {
15108 if (SrcEltTy == SmallestEltTy)
15113 DAG.
getNode(AArch64ISD::NVCAST,
DL, ShuffleVT, Src.ShuffleVec);
15119 Src.WindowBase *= Src.WindowScale;
15124 for (
auto Src : Sources)
15125 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
15133 if (Entry.isUndef())
15136 auto Src =
find(Sources, Entry.getOperand(0));
15145 int LanesDefined = BitsDefined / BitsPerShuffleLane;
15149 int *LaneMask = &Mask[i * ResMultiplier];
15151 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
15152 ExtractBase += NumElts * (Src - Sources.
begin());
15153 for (
int j = 0; j < LanesDefined; ++j)
15154 LaneMask[j] = ExtractBase + j;
15159 LLVM_DEBUG(
dbgs() <<
"Reshuffle failed: illegal shuffle mask\n");
15165 for (
unsigned i = 0; i < Sources.
size(); ++i)
15172 V = DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, Shuffle);
15178 dbgs() <<
"Reshuffle, creating node: "; V.dump(););
15197 unsigned ExpectedElt =
Imm;
15198 for (
unsigned i = 1; i < NumElts; ++i) {
15202 if (ExpectedElt == NumElts)
15207 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
15218 if (V.getValueType() != MVT::v16i8)
15220 assert(V.getNumOperands() == 16 &&
"Expected 16 operands on the BUILDVECTOR");
15222 for (
unsigned X = 0;
X < 4;
X++) {
15234 for (
unsigned Y = 1;
Y < 4;
Y++) {
15250 V.getOperand(0).getOperand(0), V.getOperand(4).getOperand(0),
15251 V.getOperand(8).getOperand(0), V.getOperand(12).getOperand(0)};
15253 if (V.getValueType() == MVT::v4i32)
15269 unsigned &DupLaneOp) {
15271 "Only possible block sizes for wide DUP are: 16, 32, 64");
15290 for (
size_t BlockIndex = 0; BlockIndex < NumBlocks; BlockIndex++)
15291 for (
size_t I = 0;
I < NumEltsPerBlock;
I++) {
15292 int Elt = M[BlockIndex * NumEltsPerBlock +
I];
15296 if ((
unsigned)Elt >= SingleVecNumElements)
15298 if (BlockElts[
I] < 0)
15299 BlockElts[
I] = Elt;
15300 else if (BlockElts[
I] != Elt)
15309 auto FirstRealEltIter =
find_if(BlockElts, [](
int Elt) {
return Elt >= 0; });
15310 assert(FirstRealEltIter != BlockElts.
end() &&
15311 "Shuffle with all-undefs must have been caught by previous cases, "
15313 if (FirstRealEltIter == BlockElts.
end()) {
15319 size_t FirstRealIndex = FirstRealEltIter - BlockElts.
begin();
15321 if ((
unsigned)*FirstRealEltIter < FirstRealIndex)
15324 size_t Elt0 = *FirstRealEltIter - FirstRealIndex;
15327 if (Elt0 % NumEltsPerBlock != 0)
15331 for (
size_t I = 0;
I < NumEltsPerBlock;
I++)
15332 if (BlockElts[
I] >= 0 && (
unsigned)BlockElts[
I] != Elt0 +
I)
15335 DupLaneOp = Elt0 / NumEltsPerBlock;
15344 const int *FirstRealElt =
find_if(M, [](
int Elt) {
return Elt >= 0; });
15349 APInt ExpectedElt =
APInt(MaskBits, *FirstRealElt + 1,
false,
15353 bool FoundWrongElt = std::any_of(FirstRealElt + 1, M.end(), [&](
int Elt) {
15354 return Elt != ExpectedElt++ && Elt >= 0;
15389 unsigned LaneElts,
unsigned NumElts,
15390 bool &IsLeftSlide) {
15393 int FirstIdx = Mask[LaneStart];
15394 if (FirstIdx > (
int)LaneStart && FirstIdx < (
int)(LaneStart + LaneElts)) {
15395 unsigned SlideAmt = FirstIdx - LaneStart;
15396 for (
unsigned i = 0; i < LaneElts; ++i) {
15397 int MaskIdx = Mask[LaneStart + i];
15400 if (i < LaneElts - SlideAmt) {
15402 if (MaskIdx != (
int)(LaneStart + SlideAmt + i))
15407 if (MaskIdx < (
int)NumElts)
15411 IsLeftSlide =
true;
15417 if (Mask[LaneStart] >= (
int)NumElts || Mask[LaneStart] < 0) {
15418 unsigned ZeroCount = 0;
15419 for (
unsigned i = 0; i < LaneElts; ++i) {
15420 int MaskIdx = Mask[LaneStart + i];
15421 if (MaskIdx >= 0 && MaskIdx < (
int)NumElts)
15425 if (ZeroCount > 0 && ZeroCount < LaneElts) {
15426 for (
unsigned i = ZeroCount; i < LaneElts; ++i) {
15427 int MaskIdx = Mask[LaneStart + i];
15430 if (MaskIdx != (
int)(LaneStart + i - ZeroCount))
15433 IsLeftSlide =
false;
15442 SDValue V2,
unsigned &ShiftAmount,
15443 bool &IsRightShift,
15444 unsigned &MatchedLaneSize) {
15446 if (VTSize != 64 && VTSize != 128)
15456 if (V1IsZeros == V2IsZeros)
15469 for (
unsigned LaneSize : {64u, 32u, 16u}) {
15470 if (LaneSize < EltSize * 2)
15472 unsigned LaneElts = LaneSize / EltSize;
15473 unsigned NumLanes = VTSize / LaneSize;
15475 bool FirstIsLeftSlide;
15476 unsigned FirstSlideAmt =
15478 if (FirstSlideAmt == 0)
15482 bool AllMatch =
true;
15483 for (
unsigned Lane = 1; Lane < NumLanes; Lane++) {
15485 unsigned SlideAmt =
15486 checkLaneSlide(Mask, Lane * LaneElts, LaneElts, NumElts, IsLeftSlide);
15487 if (SlideAmt != FirstSlideAmt || IsLeftSlide != FirstIsLeftSlide) {
15495 ShiftAmount = FirstSlideAmt * EltSize;
15496 IsRightShift = FirstIsLeftSlide;
15497 if (ShiftAmount > 0 && ShiftAmount < LaneSize) {
15498 MatchedLaneSize = LaneSize;
15510 bool &ReverseEXT,
unsigned &
Imm) {
15512 unsigned OtherBase = SplatOperand == 0 ? NumElts : 0;
15513 auto IsSplatElt = [=](
int Elt) {
15515 (SplatOperand == 0 ? Elt < (int)NumElts : Elt >= (int)NumElts);
15518 unsigned PrefixSplatElts = 0;
15519 while (PrefixSplatElts != NumElts && IsSplatElt(M[PrefixSplatElts]))
15522 if (PrefixSplatElts > 0 && PrefixSplatElts < NumElts) {
15524 for (
unsigned I = PrefixSplatElts;
I != NumElts; ++
I) {
15525 int Expected = OtherBase +
I - PrefixSplatElts;
15533 ReverseEXT = SplatOperand == 1;
15534 Imm = NumElts - PrefixSplatElts;
15539 unsigned SuffixSplatElts = 0;
15540 while (SuffixSplatElts != NumElts &&
15541 IsSplatElt(M[NumElts - 1 - SuffixSplatElts]))
15544 if (0 < SuffixSplatElts && SuffixSplatElts < NumElts) {
15546 for (
unsigned I = 0;
I != NumElts - SuffixSplatElts; ++
I) {
15547 int Expected = OtherBase +
I + SuffixSplatElts;
15555 ReverseEXT = SplatOperand == 0;
15556 Imm = SuffixSplatElts;
15565 bool &DstIsLeft,
int &Anomaly) {
15566 if (M.size() !=
static_cast<size_t>(NumInputElements))
15569 int NumLHSMatch = 0, NumRHSMatch = 0;
15570 int LastLHSMismatch = -1, LastRHSMismatch = -1;
15572 for (
int i = 0; i < NumInputElements; ++i) {
15582 LastLHSMismatch = i;
15584 if (M[i] == i + NumInputElements)
15587 LastRHSMismatch = i;
15590 if (NumLHSMatch == NumInputElements - 1) {
15592 Anomaly = LastLHSMismatch;
15594 }
else if (NumRHSMatch == NumInputElements - 1) {
15596 Anomaly = LastRHSMismatch;
15609 for (
int I = 0,
E = NumElts / 2;
I !=
E;
I++) {
15614 int Offset = NumElts / 2;
15615 for (
int I = NumElts / 2,
E = NumElts;
I !=
E;
I++) {
15616 if (Mask[
I] !=
I + SplitLHS *
Offset)
15625 EVT VT =
Op.getValueType();
15634 bool SplitV0 = V0.getValueSizeInBits() == 128;
15643 if (
V1.getValueSizeInBits() == 128) {
15658 unsigned OpNum = (PFEntry >> 26) & 0x0F;
15659 unsigned LHSID = (PFEntry >> 13) & ((1 << 13) - 1);
15660 unsigned RHSID = (PFEntry >> 0) & ((1 << 13) - 1);
15682 if (LHSID == (1 * 9 + 2) * 9 + 3)
15684 assert(LHSID == ((4 * 9 + 5) * 9 + 6) * 9 + 7 &&
"Illegal OP_COPY!");
15688 if (OpNum == OP_MOVLANE) {
15690 auto getPFIDLane = [](
unsigned ID,
int Elt) ->
int {
15691 assert(Elt < 4 &&
"Expected Perfect Lanes to be less than 4");
15697 return (ID % 9 == 8) ? -1 : ID % 9;
15706 assert(RHSID < 8 &&
"Expected a lane index for RHSID!");
15707 unsigned ExtLane = 0;
15713 int MaskElt = getPFIDLane(ID, (RHSID & 0x01) << 1) >> 1;
15715 MaskElt = (getPFIDLane(ID, ((RHSID & 0x01) << 1) + 1) - 1) >> 1;
15716 assert(MaskElt >= 0 &&
"Didn't expect an undef movlane index!");
15717 ExtLane = MaskElt < 2 ? MaskElt : (MaskElt - 2);
15718 Input = MaskElt < 2 ?
V1 : V2;
15724 "Expected 16 or 32 bit shuffle elements");
15729 int MaskElt = getPFIDLane(ID, RHSID);
15730 assert(MaskElt >= 0 &&
"Didn't expect an undef movlane index!");
15731 ExtLane = MaskElt < 4 ? MaskElt : (MaskElt - 4);
15732 Input = MaskElt < 4 ?
V1 : V2;
15734 if (VT == MVT::v4i16) {
15740 Input.getValueType().getVectorElementType(),
15762 return DAG.
getNode(AArch64ISD::REV64,
DL, VT, OpLHS);
15767 return DAG.
getNode(AArch64ISD::REV32,
DL, VT, OpLHS);
15769 assert(VT == MVT::v8i8 || VT == MVT::v16i8);
15770 EVT BSVT = VT == MVT::v8i8 ? MVT::v4i16 : MVT::v8i16;
15772 AArch64ISD::NVCAST,
DL, VT,
15774 DAG.
getNode(AArch64ISD::NVCAST,
DL, BSVT, OpLHS)));
15782 if (EltTy == MVT::i8)
15783 Opcode = AArch64ISD::DUPLANE8;
15784 else if (EltTy == MVT::i16 || EltTy == MVT::f16 || EltTy == MVT::bf16)
15785 Opcode = AArch64ISD::DUPLANE16;
15786 else if (EltTy == MVT::i32 || EltTy == MVT::f32)
15787 Opcode = AArch64ISD::DUPLANE32;
15788 else if (EltTy == MVT::i64 || EltTy == MVT::f64)
15789 Opcode = AArch64ISD::DUPLANE64;
15796 return DAG.
getNode(Opcode,
DL, VT, OpLHS, Lane);
15802 return DAG.
getNode(AArch64ISD::EXT,
DL, VT, OpLHS, OpRHS,
15806 return DAG.
getNode(AArch64ISD::UZP1,
DL, VT, OpLHS, OpRHS);
15808 return DAG.
getNode(AArch64ISD::UZP2,
DL, VT, OpLHS, OpRHS);
15810 return DAG.
getNode(AArch64ISD::ZIP1,
DL, VT, OpLHS, OpRHS);
15812 return DAG.
getNode(AArch64ISD::ZIP2,
DL, VT, OpLHS, OpRHS);
15814 return DAG.
getNode(AArch64ISD::TRN1,
DL, VT, OpLHS, OpRHS);
15816 return DAG.
getNode(AArch64ISD::TRN2,
DL, VT, OpLHS, OpRHS);
15827 EVT EltVT =
Op.getValueType().getVectorElementType();
15840 MVT IndexVT = MVT::v8i8;
15841 unsigned IndexLen = 8;
15842 if (
Op.getValueSizeInBits() == 128) {
15843 IndexVT = MVT::v16i8;
15848 for (
int Val : ShuffleMask) {
15849 for (
unsigned Byte = 0; Byte < BytesPerElt; ++Byte) {
15850 unsigned Offset = Byte + Val * BytesPerElt;
15853 if (IsUndefOrZero &&
Offset >= IndexLen)
15863 if (IsUndefOrZero) {
15872 if (IndexLen == 8) {
15897 if (EltType == MVT::i8)
15898 return AArch64ISD::DUPLANE8;
15899 if (EltType == MVT::i16 || EltType == MVT::f16 || EltType == MVT::bf16)
15900 return AArch64ISD::DUPLANE16;
15901 if (EltType == MVT::i32 || EltType == MVT::f32)
15902 return AArch64ISD::DUPLANE32;
15903 if (EltType == MVT::i64 || EltType == MVT::f64)
15904 return AArch64ISD::DUPLANE64;
15912 auto getScaledOffsetDup = [](
SDValue BitCast,
int &LaneC,
MVT &CastVT) {
15923 unsigned ExtIdxInBits = ExtIdx * SrcEltBitWidth;
15925 if (ExtIdxInBits % CastedEltBitWidth != 0)
15933 LaneC += ExtIdxInBits / CastedEltBitWidth;
15940 unsigned SrcVecNumElts =
15947 if (getScaledOffsetDup(V, Lane, CastVT)) {
15948 V = DAG.
getBitcast(CastVT, V.getOperand(0).getOperand(0));
15950 V.getOperand(0).getValueType().is128BitVector()) {
15953 Lane += V.getConstantOperandVal(1);
15954 V = V.getOperand(0);
15980 EVT VT =
Op.getValueType();
15990 if (ElementSize > 32 || ElementSize == 1)
16020 EVT VT =
Op.getValueType();
16037 for (
unsigned I = 0;
I < 16;
I++) {
16038 if (ShuffleMask[
I] < 16)
16044 TBLMaskParts[
I] = DAG.
getConstant(
C->getSExtValue() + 32,
DL, MVT::i32);
16058AArch64TargetLowering::LowerEXTEND_VECTOR_INREG(
SDValue Op,
16061 EVT VT =
Op.getValueType();
16065 unsigned UnpackOpcode =
Signed ? AArch64ISD::SUNPKLO : AArch64ISD::UUNPKLO;
16073 Val = DAG.
getNode(UnpackOpcode,
DL, MVT::nxv8i16, Val);
16074 if (VT == MVT::nxv8i16)
16078 Val = DAG.
getNode(UnpackOpcode,
DL, MVT::nxv4i32, Val);
16079 if (VT == MVT::nxv4i32)
16083 Val = DAG.
getNode(UnpackOpcode,
DL, MVT::nxv2i64, Val);
16084 assert(VT == MVT::nxv2i64 &&
"Unexpected result type!");
16095AArch64TargetLowering::LowerZERO_EXTEND_VECTOR_INREG(
SDValue Op,
16098 EVT VT =
Op.getValueType();
16101 return LowerEXTEND_VECTOR_INREG(
Op, DAG);
16106 "Unexpected extension factor.");
16113 DAG.
getNode(AArch64ISD::ZIP1,
DL, SrcVT, SrcOp, Zeros));
16119 EVT VT =
Op.getValueType();
16124 return LowerFixedLengthVECTOR_SHUFFLEToSVE(
Op, DAG);
16130 ArrayRef<int> ShuffleMask = SVN->
getMask();
16135 assert(
V1.getValueType() == VT &&
"Unexpected VECTOR_SHUFFLE type!");
16137 "Unexpected VECTOR_SHUFFLE mask size!");
16149 return DAG.
getNode(AArch64ISD::DUP,
DL,
V1.getValueType(),
16155 return DAG.
getNode(AArch64ISD::DUP,
DL, VT,
V1.getOperand(Lane));
16158 unsigned Opcode =
getDUPLANEOp(
V1.getValueType().getVectorElementType());
16163 for (
unsigned LaneSize : {64U, 32U, 16U}) {
16166 unsigned Opcode = LaneSize == 64 ? AArch64ISD::DUPLANE64
16167 : LaneSize == 32 ? AArch64ISD::DUPLANE32
16168 : AArch64ISD::DUPLANE16;
16183 if (
isREVMask(ShuffleMask, EltSize, NumElts, 64))
16184 return DAG.
getNode(AArch64ISD::REV64,
DL,
V1.getValueType(),
V1);
16185 if (
isREVMask(ShuffleMask, EltSize, NumElts, 32))
16186 return DAG.
getNode(AArch64ISD::REV32,
DL,
V1.getValueType(),
V1);
16187 if (
isREVMask(ShuffleMask, EltSize, NumElts, 16)) {
16188 EVT VT =
V1.getValueType();
16189 assert(VT == MVT::v8i8 || VT == MVT::v16i8);
16190 EVT BSVT = VT == MVT::v8i8 ? MVT::v4i16 : MVT::v8i16;
16192 AArch64ISD::NVCAST,
DL, VT,
16197 if (((NumElts == 8 && EltSize == 16) || (NumElts == 16 && EltSize == 8)) &&
16200 return DAG.
getNode(AArch64ISD::EXT,
DL, VT, Rev, Rev,
16206 unsigned ShiftAmount;
16208 unsigned MatchedLaneSize;
16211 IsRightShift, MatchedLaneSize)) {
16217 unsigned Opc = IsRightShift ? AArch64ISD::VLSHR : AArch64ISD::VSHL;
16220 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, Shifted);
16228 for (
unsigned SplatOperand : {0
U, 1U}) {
16229 if ((SplatOperand == 0 && !IsSplat1) || (SplatOperand == 1 && !IsSplat2))
16232 bool ReverseSplatEXT =
false;
16238 if (ReverseSplatEXT)
16241 return DAG.
getNode(AArch64ISD::EXT,
DL, VT, ExtOp1, ExtOp2,
16246 bool ReverseEXT =
false;
16252 return DAG.
getNode(AArch64ISD::EXT,
DL,
V1.getValueType(),
V1, V2,
16260 unsigned WhichResult;
16261 unsigned OperandOrder;
16262 if (
isZIPMask(ShuffleMask, NumElts, WhichResult, OperandOrder)) {
16263 unsigned Opc = (WhichResult == 0) ? AArch64ISD::ZIP1 : AArch64ISD::ZIP2;
16264 return DAG.
getNode(
Opc,
DL,
V1.getValueType(), OperandOrder == 0 ?
V1 : V2,
16265 OperandOrder == 0 ? V2 :
V1);
16267 if (
isUZPMask(ShuffleMask, NumElts, WhichResult)) {
16268 unsigned Opc = (WhichResult == 0) ? AArch64ISD::UZP1 : AArch64ISD::UZP2;
16271 if (
isTRNMask(ShuffleMask, NumElts, WhichResult, OperandOrder)) {
16272 unsigned Opc = (WhichResult == 0) ? AArch64ISD::TRN1 : AArch64ISD::TRN2;
16273 return DAG.
getNode(
Opc,
DL,
V1.getValueType(), OperandOrder == 0 ?
V1 : V2,
16274 OperandOrder == 0 ? V2 :
V1);
16278 unsigned Opc = (WhichResult == 0) ? AArch64ISD::ZIP1 : AArch64ISD::ZIP2;
16282 unsigned Opc = (WhichResult == 0) ? AArch64ISD::UZP1 : AArch64ISD::UZP2;
16286 unsigned Opc = (WhichResult == 0) ? AArch64ISD::TRN1 : AArch64ISD::TRN2;
16295 int NumInputElements =
V1.getValueType().getVectorNumElements();
16296 if (
isINSMask(ShuffleMask, NumInputElements, DstIsLeft, Anomaly)) {
16301 int SrcLane = ShuffleMask[Anomaly];
16302 if (SrcLane >= NumInputElements) {
16304 SrcLane -= NumElts;
16311 ScalarVT = MVT::i32;
16324 if (NumElts == 4) {
16325 unsigned PFIndexes[4];
16326 for (
unsigned i = 0; i != 4; ++i) {
16327 if (ShuffleMask[i] < 0)
16330 PFIndexes[i] = ShuffleMask[i];
16334 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
16335 PFIndexes[2] * 9 + PFIndexes[3];
16345 "Expected larger vector element sizes to be handled already");
16347 for (
int M : ShuffleMask)
16349 M >=
static_cast<int>(NumElts) ? 0 : 0xffffffff,
DL, MVT::i32));
16363 EVT VT =
Op.getValueType();
16366 return LowerToScalableOp(
Op, DAG);
16383 if (VT == MVT::nxv1i1)
16386 MVT::nxv2i1, ID, Zero, SplatVal),
16395 EVT VT =
Op.getValueType();
16408 if (CIdx && (CIdx->getZExtValue() <= 3)) {
16410 return DAG.
getNode(AArch64ISD::DUPLANE128,
DL, VT,
Op.getOperand(1), CI);
16432 SDValue TBL = DAG.
getNode(AArch64ISD::TBL,
DL, MVT::nxv2i64, V, ShuffleMask);
16438 APInt &UndefBits) {
16440 APInt SplatBits, SplatUndef;
16441 unsigned SplatBitSize;
16443 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
16446 for (
unsigned i = 0; i < NumSplats; ++i) {
16447 CnstBits <<= SplatBitSize;
16448 UndefBits <<= SplatBitSize;
16450 UndefBits |= (SplatBits ^ SplatUndef).zextOrTrunc(VT.
getSizeInBits());
16461 const APInt &Bits) {
16462 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16464 EVT VT =
Op.getValueType();
16473 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, Mov);
16484 EVT VT =
Op.getValueType();
16489 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16492 bool isAdvSIMDModImm =
false;
16512 if (isAdvSIMDModImm) {
16526 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, Mov);
16537 EVT VT =
Op.getValueType();
16542 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16545 bool isAdvSIMDModImm =
false;
16557 if (isAdvSIMDModImm) {
16571 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, Mov);
16581 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16583 EVT VT =
Op.getValueType();
16585 bool isAdvSIMDModImm =
false;
16597 if (isAdvSIMDModImm) {
16602 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, Mov);
16611 const APInt &Bits) {
16612 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16614 EVT VT =
Op.getValueType();
16623 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, Mov);
16632 const APInt &Bits) {
16633 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16635 EVT VT =
Op.getValueType();
16638 bool isAdvSIMDModImm =
false;
16642 MovTy = isWide ? MVT::v4f32 : MVT::v2f32;
16647 MovTy = MVT::v2f64;
16650 if (isAdvSIMDModImm) {
16654 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, Mov);
16674 for (
unsigned i = 1; i < NumElts; ++i)
16683 while (
N.getOpcode() == AArch64ISD::REINTERPRET_CAST)
16684 N =
N.getOperand(0);
16690 unsigned NumElts =
N.getValueType().getVectorMinNumElements();
16693 while (
N.getOpcode() == AArch64ISD::REINTERPRET_CAST) {
16694 N =
N.getOperand(0);
16697 if (
N.getValueType().getVectorMinNumElements() < NumElts)
16707 if (
N.getOpcode() == AArch64ISD::PTRUE &&
16708 N.getConstantOperandVal(0) == AArch64SVEPredPattern::all)
16709 return N.getValueType().getVectorMinNumElements() >= NumElts;
16721 EVT VT =
N->getValueType(0);
16731 SDValue FirstOp =
N->getOperand(0);
16732 unsigned FirstOpc = FirstOp.
getOpcode();
16733 SDValue SecondOp =
N->getOperand(1);
16734 unsigned SecondOpc = SecondOp.
getOpcode();
16741 if ((FirstOpc ==
ISD::AND || FirstOpc == AArch64ISD::BICi) &&
16742 (SecondOpc == AArch64ISD::VSHL || SecondOpc == AArch64ISD::VLSHR ||
16743 SecondOpc == AArch64ISD::SHL_PRED ||
16744 SecondOpc == AArch64ISD::SRL_PRED)) {
16748 }
else if ((SecondOpc ==
ISD::AND || SecondOpc == AArch64ISD::BICi) &&
16749 (FirstOpc == AArch64ISD::VSHL || FirstOpc == AArch64ISD::VLSHR ||
16750 FirstOpc == AArch64ISD::SHL_PRED ||
16751 FirstOpc == AArch64ISD::SRL_PRED)) {
16758 bool IsShiftRight = Shift.
getOpcode() == AArch64ISD::VLSHR ||
16759 Shift.
getOpcode() == AArch64ISD::SRL_PRED;
16760 bool ShiftHasPredOp = Shift.
getOpcode() == AArch64ISD::SHL_PRED ||
16761 Shift.
getOpcode() == AArch64ISD::SRL_PRED;
16765 if (ShiftHasPredOp) {
16771 C2 =
C.getZExtValue();
16774 C2 = C2node->getZExtValue();
16788 assert(C1nodeImm && C1nodeShift);
16790 C1AsAPInt = C1AsAPInt.
zextOrTrunc(ElemSizeInBits);
16796 if (C2 > ElemSizeInBits)
16801 if (C1AsAPInt != RequiredC1)
16809 unsigned Inst = IsShiftRight ? AArch64ISD::VSRI : AArch64ISD::VSLI;
16814 EVT VT =
N->getValueType(0);
16815 assert(VT.
isVector() &&
"Expected vector type in tryLowerToBSL\n");
16833 for (
int i = 1; i >= 0; --i) {
16834 for (
int j = 1; j >= 0; --j) {
16860 if (
Sub.getOperand(1) !=
Add.getOperand(0))
16863 return DAG.
getNode(AArch64ISD::BSP,
DL, VT,
Sub, SubSibling, AddSibling);
16871 for (
int i = 1; i >= 0; --i)
16872 for (
int j = 1; j >= 0; --j) {
16883 if (!BVN0 || !BVN1)
16886 bool FoundMatch =
true;
16890 if (!CN0 || !CN1 ||
16893 FoundMatch =
false;
16908 !Subtarget->isNeonAvailable()))
16909 return LowerToScalableOp(
Op, DAG);
16918 EVT VT =
Op.getValueType();
16923 BuildVectorSDNode *BVN =
16927 LHS =
Op.getOperand(1);
16945 UndefBits, &
LHS)) ||
16961 EVT VT =
Op.getValueType();
16975 CstLane->getAPIntValue().trunc(EltTy.
getSizeInBits()).getZExtValue(),
16979 }
else if (Lane.getOpcode() ==
ISD::UNDEF) {
16982 assert(Lane.getValueType() == MVT::i32 &&
16983 "Unexpected BUILD_VECTOR operand type");
16985 Ops.push_back(Lane);
16992 EVT VT =
Op.getValueType();
17000 int32_t ImmVal, ShiftVal;
17009 return DAG.
getNode(AArch64ISD::NVCAST,
DL, VT, SplatVal);
17014 EVT VT =
Op.getValueType();
17016 "Expected a legal NEON vector");
17022 auto TryMOVIWithBits = [&](
APInt DefBits) {
17036 APInt NotDefBits = ~DefBits;
17046 if (
SDValue R = TryMOVIWithBits(DefBits))
17048 if (
SDValue R = TryMOVIWithBits(UndefBits))
17056 auto TryWithFNeg = [&](
APInt DefBits,
MVT FVT) {
17062 unsigned NumElts = VT.
getSizeInBits() / FVT.getScalarSizeInBits();
17063 for (
unsigned i = 0; i < NumElts; i++)
17064 NegBits |= Neg << (FVT.getScalarSizeInBits() * i);
17065 NegBits = DefBits ^ NegBits;
17069 if (
SDValue NewOp = TryMOVIWithBits(NegBits)) {
17073 AArch64ISD::NVCAST,
DL, VT,
17075 DAG.
getNode(AArch64ISD::NVCAST,
DL, VFVT, NewOp)));
17080 if ((R = TryWithFNeg(DefBits, MVT::f32)) ||
17081 (R = TryWithFNeg(DefBits, MVT::f64)) ||
17082 (ST->hasFullFP16() && (R = TryWithFNeg(DefBits, MVT::f16))))
17089SDValue AArch64TargetLowering::LowerFixedLengthBuildVectorToSVE(
17091 EVT VT =
Op.getValueType();
17115 NumElems -
count_if(
Op->op_values(), IsExtractElt) > 4)
17122 return Op.isUndef() ? Poison
17123 : DAG.getNode(ISD::INSERT_VECTOR_ELT, DL,
17124 ContainerVT, Poison, Op, ZeroI64);
17128 while (Intermediates.
size() > 1) {
17131 for (
unsigned I = 0;
I < Intermediates.
size();
I += 2) {
17134 Intermediates[
I / 2] =
17136 : DAG.
getNode(AArch64ISD::ZIP1,
DL, ZipVT, Op0, Op1);
17139 Intermediates.
resize(Intermediates.
size() / 2);
17150 EVT VT =
Op.getValueType();
17152 bool OverrideNEON = !Subtarget->isNeonAvailable();
17153 if (!OverrideNEON && Subtarget->isSVEorStreamingSVEAvailable()) {
17157 if (Seq->first.sge(-16) && Seq->first.slt(16) && Seq->second.sge(-16) &&
17158 Seq->second.slt(16))
17159 OverrideNEON =
true;
17163 return LowerFixedLengthBuildVectorToSVE(
Op, DAG);
17181 Const->getAPIntValue().zextOrTrunc(BitSize).getZExtValue());
17182 if (Val.isZero() || (VT.
isInteger() && Val.isAllOnes()))
17186 if (
Const->isZero() && !
Const->isNegative())
17207 bool isOnlyLowElement =
true;
17208 bool usesOnlyOneValue =
true;
17209 bool usesOnlyOneConstantValue =
true;
17211 bool AllLanesExtractElt =
true;
17212 unsigned NumConstantLanes = 0;
17213 unsigned NumDifferentLanes = 0;
17214 unsigned NumUndefLanes = 0;
17217 SmallMapVector<SDValue, unsigned, 16> DifferentValueMap;
17218 unsigned ConsecutiveValCount = 0;
17223 bool MaybeLowHalfZeroHigh =
17225 unsigned HalfElts = MaybeLowHalfZeroHigh ? (NumElts >> 1) : 0;
17226 SDValue LowHalfFirstVal = MaybeLowHalfZeroHigh ?
Op.getOperand(0) :
SDValue();
17227 for (
unsigned i = 0; i < NumElts; ++i) {
17230 AllLanesExtractElt =
false;
17233 MaybeLowHalfZeroHigh =
false;
17237 isOnlyLowElement =
false;
17242 ++NumConstantLanes;
17243 if (!ConstantValue.
getNode())
17245 else if (ConstantValue != V)
17246 usesOnlyOneConstantValue =
false;
17249 if (!
Value.getNode())
17251 else if (V !=
Value) {
17252 usesOnlyOneValue =
false;
17253 ++NumDifferentLanes;
17256 if (PrevVal != V) {
17257 ConsecutiveValCount = 0;
17260 if (MaybeLowHalfZeroHigh) {
17261 if (i < HalfElts) {
17262 if (V != LowHalfFirstVal)
17263 MaybeLowHalfZeroHigh =
false;
17264 }
else if (!IsZero(V)) {
17265 MaybeLowHalfZeroHigh =
false;
17280 DifferentValueMap[
V] = ++ConsecutiveValCount;
17283 if (!
Value.getNode()) {
17285 dbgs() <<
"LowerBUILD_VECTOR: value undefined, creating undef node\n");
17293 LLVM_DEBUG(
dbgs() <<
"LowerBUILD_VECTOR: only low element used, creating 1 "
17294 "SCALAR_TO_VECTOR node\n");
17298 if (MaybeLowHalfZeroHigh && LowHalfFirstVal.
getNode() &&
17309 : DAG.
getNode(AArch64ISD::DUP,
DL, HalfVT, LowHalfFirstVal);
17314 if (AllLanesExtractElt) {
17315 SDNode *
Vector =
nullptr;
17320 for (
unsigned i = 0; i < NumElts; ++i) {
17322 const SDNode *
N =
V.getNode();
17347 if (Val == 2 * i) {
17351 if (Val - 1 == 2 * i) {
17375 if (usesOnlyOneValue) {
17378 Value.getValueType() != VT) {
17380 dbgs() <<
"LowerBUILD_VECTOR: use DUP for non-constant splats\n");
17388 if (
Value.getValueSizeInBits() == 64) {
17390 dbgs() <<
"LowerBUILD_VECTOR: DUPLANE works on 128-bit vectors, "
17402 assert ((EltTy == MVT::f16 || EltTy == MVT::bf16 || EltTy == MVT::f32 ||
17403 EltTy == MVT::f64) &&
"Unsupported floating-point vector type");
17405 dbgs() <<
"LowerBUILD_VECTOR: float constant splats, creating int "
17406 "BITCASTS, and try again\n");
17408 for (
unsigned i = 0; i < NumElts; ++i)
17412 LLVM_DEBUG(
dbgs() <<
"LowerBUILD_VECTOR: trying to lower new vector: ";
17414 Val = LowerBUILD_VECTOR(Val, DAG);
17424 bool PreferDUPAndInsert =
17426 NumDifferentLanes < ((NumElts - NumUndefLanes) / 2) &&
17427 NumDifferentLanes >= NumConstantLanes;
17433 if (!PreferDUPAndInsert && NumConstantLanes > 0 && usesOnlyOneConstantValue) {
17437 APInt ConstantValueAPInt(1, 0);
17439 ConstantValueAPInt =
C->getAPIntValue().zextOrTrunc(BitSize);
17441 !ConstantValueAPInt.isAllOnes()) {
17445 Val = DAG.
getNode(AArch64ISD::DUP,
DL, VT, ConstantValue);
17449 for (
unsigned i = 0; i < NumElts; ++i) {
17466 const SDLoc
DL(
Op);
17467 APInt PackedVal(64, 0);
17468 unsigned BitPos = 0;
17475 LaneBits = APInt(EltSizeInBits, 0);
17477 LaneBits =
C->getAPIntValue();
17479 LaneBits = CFP->getValueAPF().bitcastToAPInt();
17484 BitPos += EltSizeInBits;
17491 if (Insns.
size() > 2)
17502 dbgs() <<
"LowerBUILD_VECTOR: all elements are constant, use default "
17514 if (NumElts >= 4) {
17522 if (PreferDUPAndInsert) {
17527 for (
unsigned I = 0;
I < NumElts; ++
I)
17538 if (DifferentValueMap.
size() == 2 && NumUndefLanes == 0) {
17550 bool canUseVECTOR_CONCAT =
true;
17551 for (
auto Pair : DifferentValueMap) {
17553 if (Pair.second != NumElts / 2)
17554 canUseVECTOR_CONCAT =
false;
17567 if (canUseVECTOR_CONCAT) {
17590 if (NumElts >= 8) {
17591 SmallVector<int, 16> MaskVec;
17593 SDValue FirstLaneVal =
Op.getOperand(0);
17594 for (
unsigned i = 0; i < NumElts; ++i) {
17596 if (FirstLaneVal == Val)
17620 dbgs() <<
"LowerBUILD_VECTOR: alternatives failed, creating sequence "
17621 "of INSERT_VECTOR_ELT\n");
17638 LLVM_DEBUG(
dbgs() <<
"Creating node for op0, it is not undefined:\n");
17644 dbgs() <<
"Creating nodes for the other vector elements:\n";
17646 for (; i < NumElts; ++i) {
17657 dbgs() <<
"LowerBUILD_VECTOR: use default expansion, failed to find "
17658 "better alternative\n");
17665 !Subtarget->isNeonAvailable()))
17666 return LowerFixedLengthConcatVectorsToSVE(
Op, DAG);
17668 assert(
Op.getValueType().isScalableVector() &&
17670 "Expected legal scalable vector type!");
17675 "Unexpected number of operands in CONCAT_VECTORS");
17677 if (NumOperands == 2)
17682 while (ConcatOps.size() > 1) {
17683 for (
unsigned I = 0,
E = ConcatOps.size();
I !=
E;
I += 2) {
17686 EVT SubVT =
V1.getValueType();
17691 ConcatOps.resize(ConcatOps.size() / 2);
17693 return ConcatOps[0];
17704 !Subtarget->isNeonAvailable()))
17705 return LowerFixedLengthInsertVectorElt(
Op, DAG);
17707 EVT VT =
Op.getValueType();
17716 if (VT == MVT::nxv1i1) {
17720 WidenVec, Elt, Idx);
17729 PromoteVec, Elt, Idx);
17742AArch64TargetLowering::LowerEXTRACT_VECTOR_ELT(
SDValue Op,
17745 EVT VT =
Op.getOperand(0).getValueType();
17751 if (VT == MVT::nxv1i1) {
17755 WidenedPred,
Op.getOperand(1));
17762 MVT ExtractTy = VectorVT == MVT::nxv2i64 ? MVT::i64 : MVT::i32;
17764 Extend,
Op.getOperand(1));
17769 return LowerFixedLengthExtractVectorElt(
Op, DAG);
17777 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
17778 VT == MVT::v2i64 || VT == MVT::v4f32 || VT == MVT::v2f64 ||
17779 VT == MVT::v8f16 || VT == MVT::v8bf16)
17782 if (VT != MVT::v8i8 && VT != MVT::v4i16 && VT != MVT::v2i32 &&
17783 VT != MVT::v1i64 && VT != MVT::v2f32 && VT != MVT::v4f16 &&
17794 if (ExtrTy == MVT::i16 || ExtrTy == MVT::i8)
17804 EVT VT =
Op.getValueType();
17806 "Only cases that extract a fixed length vector are supported!");
17807 EVT InVT =
Op.getOperand(0).getValueType();
17815 unsigned Idx =
Op.getConstantOperandVal(1);
17834 if (PackedVT != InVT) {
17857 assert(
Op.getValueType().isScalableVector() &&
17858 "Only expect to lower inserts into scalable vectors!");
17860 EVT InVT =
Op.getOperand(1).getValueType();
17861 unsigned Idx =
Op.getConstantOperandVal(2);
17866 EVT VT =
Op.getValueType();
17880 if (Idx < (NumElts / 2))
17904 Vec0 = getSVESafeBitCast(NarrowVT, Vec0, DAG);
17905 Vec1 = getSVESafeBitCast(NarrowVT, Vec1, DAG);
17909 Vec1 = DAG.
getNode(AArch64ISD::NVCAST,
DL, NarrowVT, Vec1);
17918 HiVec0 = DAG.
getNode(AArch64ISD::NVCAST,
DL, NarrowVT, HiVec0);
17919 Narrow = DAG.
getNode(AArch64ISD::UZP1,
DL, NarrowVT, Vec1, HiVec0);
17922 "Invalid subvector index!");
17924 LoVec0 = DAG.
getNode(AArch64ISD::NVCAST,
DL, NarrowVT, LoVec0);
17925 Narrow = DAG.
getNode(AArch64ISD::UZP1,
DL, NarrowVT, LoVec0, Vec1);
17928 return getSVESafeBitCast(VT, Narrow, DAG);
17936 std::optional<unsigned> PredPattern =
17948 if (
Op.getOpcode() != AArch64ISD::DUP &&
17961 SplatVal =
Op->getConstantOperandVal(0);
17962 if (
Op.getValueType().getVectorElementType() != MVT::i64)
17963 SplatVal = (int32_t)SplatVal;
17971 SplatVal = -SplatVal;
17979 EVT VT =
Op.getValueType();
17983 return LowerFixedLengthVectorIntDivideToSVE(
Op, DAG);
17985 unsigned Opc =
Op.getOpcode();
17997 DAG.
getNode(AArch64ISD::ASRD_MERGE_OP1,
DL, VT, Pg,
Op->getOperand(0),
18005 if (VT == MVT::nxv4i32 || VT == MVT::nxv2i64) {
18007 return DAG.
getNode(MaskedOpcode,
DL, VT,
Op.getOperand(0),
Op.getOperand(1),
18014 if (VT == MVT::nxv16i8)
18015 WidenedVT = MVT::nxv8i16;
18016 else if (VT == MVT::nxv8i16)
18017 WidenedVT = MVT::nxv4i32;
18021 unsigned UnpkLo =
Signed ? AArch64ISD::SUNPKLO : AArch64ISD::UUNPKLO;
18022 unsigned UnpkHi =
Signed ? AArch64ISD::SUNPKHI : AArch64ISD::UUNPKHI;
18031 return DAG.
getNode(AArch64ISD::UZP1,
DL, VT, ResultLoCast, ResultHiCast);
18034bool AArch64TargetLowering::shouldExpandBuildVectorWithShuffles(
18035 EVT VT,
unsigned DefinedValues)
const {
18036 if (!Subtarget->isNeonAvailable())
18055 unsigned DummyUnsigned;
18063 isEXTMask(M, VT, DummyBool, DummyUnsigned) ||
18065 isTRNMask(M, NumElts, DummyUnsigned, DummyUnsigned) ||
18066 isUZPMask(M, NumElts, DummyUnsigned) ||
18067 isZIPMask(M, NumElts, DummyUnsigned, DummyUnsigned) ||
18071 isINSMask(M, NumElts, DummyBool, DummyInt) ||
18087 Op =
Op.getOperand(0);
18089 APInt SplatBits, SplatUndef;
18090 unsigned SplatBitSize;
18092 if (!BVN || !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize,
18093 HasAnyUndefs, ElementBits) ||
18094 SplatBitSize > ElementBits)
18105 assert(VT.
isVector() &&
"vector shift count is not a vector type");
18109 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
18116 assert(VT.
isVector() &&
"vector shift count is not a vector type");
18120 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
18125 EVT VT =
Op.getValueType();
18130 EVT OpVT =
Op.getOperand(0).getValueType();
18141 !Subtarget->isNeonAvailable()))
18142 return LowerFixedLengthVectorTruncateToSVE(
Op, DAG);
18145 if (VT.
is64BitVector() &&
Op.getOperand(0).getValueType().is128BitVector())
18156 unsigned &ShiftValue,
18169 ShiftValue = ShiftOp1->getZExtValue();
18178 "ResVT must be truncated or same type as the shift.");
18181 if (ShiftValue > ExtraBits && !
Add->getFlags().hasNoUnsignedWrap())
18188 uint64_t AddValue = AddOp1->getZExtValue();
18189 if (AddValue != 1ULL << (ShiftValue - 1))
18192 RShOperand =
Add->getOperand(0);
18198 EVT VT =
Op.getValueType();
18202 if (!
Op.getOperand(1).getValueType().isVector())
18206 switch (
Op.getOpcode()) {
18210 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::SHL_PRED);
18212 if (
isVShiftLImm(
Op.getOperand(1), VT,
false, Cnt) && Cnt < EltSize)
18213 return DAG.
getNode(AArch64ISD::VSHL,
DL, VT,
Op.getOperand(0),
18218 Op.getOperand(0),
Op.getOperand(1));
18222 (Subtarget->hasSVE2() ||
18223 (Subtarget->hasSME() && Subtarget->isStreaming()))) {
18225 unsigned ShiftValue;
18227 return DAG.
getNode(AArch64ISD::URSHR_I_PRED,
DL, VT,
18234 unsigned Opc =
Op.getOpcode() ==
ISD::SRA ? AArch64ISD::SRA_PRED
18235 : AArch64ISD::SRL_PRED;
18236 return LowerToPredicatedOp(
Op, DAG,
Opc);
18240 if (
isVShiftRImm(
Op.getOperand(1), VT,
false, Cnt) && Cnt < EltSize) {
18242 (
Op.getOpcode() ==
ISD::SRA) ? AArch64ISD::VASHR : AArch64ISD::VLSHR;
18251 unsigned Opc = (
Op.getOpcode() ==
ISD::SRA) ? Intrinsic::aarch64_neon_sshl
18252 : Intrinsic::aarch64_neon_ushl;
18260 return NegShiftLeft;
18268 if (
Op.getValueType().isScalableVector())
18269 return LowerToPredicatedOp(
Op, DAG, AArch64ISD::SETCC_MERGE_ZERO);
18272 !Subtarget->isNeonAvailable()))
18273 return LowerFixedLengthVectorSetccToSVE(
Op, DAG);
18278 EVT CmpVT =
LHS.getValueType().changeVectorElementTypeToInteger();
18281 if (
LHS.getValueType().getVectorElementType().isInteger())
18284 assert(((!Subtarget->hasFullFP16() &&
18285 LHS.getValueType().getVectorElementType() != MVT::f16) ||
18286 LHS.getValueType().getVectorElementType() != MVT::bf16 ||
18287 LHS.getValueType().getVectorElementType() != MVT::f128) &&
18288 "Unexpected type!");
18293 bool OneNaN =
false;
18314 bool NoNaNs =
Op->getFlags().hasNoNaNs();
18316 if (!
Cmp.getNode())
18345 unsigned ScalarOpcode;
18363 "Expected power-of-2 length vector");
18371 if (ElemVT == MVT::i1) {
18373 if (NumElems > 16) {
18376 EVT HalfVT =
Lo.getValueType();
18387 unsigned ExtendedWidth = 64;
18390 ExtendedWidth = 128;
18395 unsigned ExtendOp =
18404 NumElems == 2 && ExtendedWidth == 128) {
18405 Extended = DAG.
getBitcast(MVT::v4i32, Extended);
18406 ExtendedVT = MVT::i32;
18408 switch (ScalarOpcode) {
18429 VecVT =
Lo.getValueType();
18445 for (
unsigned Shift = NumElems / 2; Shift > 0; Shift /= 2) {
18450 Scalar = DAG.
getNode(ScalarOpcode,
DL, ScalarVT, Scalar, Shifted);
18463 EVT SrcVT = Src.getValueType();
18468 SrcVT == MVT::v2f16) {
18476 if (
SDValue Result = LowerReductionToSVE(
Op, DAG))
18480 switch (
Op.getOpcode()) {
18485 Op.getValueType(),
DL, DAG);
18505 EVT SrcVT = Src.getValueType();
18508 SDVTList SrcVTs = DAG.
getVTList(SrcVT, SrcVT);
18520 for (
unsigned I = 0;
I < Stages; ++
I) {
18522 Src = DAG.
getNode(BaseOpc,
DL, SrcVT, Src.getValue(0), Src.getValue(1));
18530 auto &Subtarget = DAG.
getSubtarget<AArch64Subtarget>();
18532 if (!Subtarget.hasLSE() && !Subtarget.outlineAtomics())
18537 MVT VT =
Op.getSimpleValueType();
18538 assert(VT != MVT::i128 &&
"Handled elsewhere, code replicated.");
18543 Op.getOperand(0),
Op.getOperand(1),
RHS,
18548AArch64TargetLowering::LowerWindowsDYNAMIC_STACKALLOC(
SDValue Op,
18553 SDNode *
Node =
Op.getNode();
18558 EVT VT =
Node->getValueType(0);
18561 "no-stack-arg-probe")) {
18563 Chain =
SP.getValue(1);
18573 RTLIB::LibcallImpl ChkStkImpl =
getLibcallImpl(RTLIB::STACK_PROBE);
18574 if (ChkStkImpl == RTLIB::Unsupported)
18583 const AArch64RegisterInfo *
TRI = Subtarget->getRegisterInfo();
18584 const uint32_t *
Mask =
TRI->getWindowsStackProbePreservedMask();
18585 if (Subtarget->hasCustomCallingConv())
18593 Chain, Callee, DAG.
getRegister(AArch64::X15, MVT::i64),
18604 Chain =
SP.getValue(1);
18618AArch64TargetLowering::LowerInlineDYNAMIC_STACKALLOC(
SDValue Op,
18621 SDNode *
Node =
Op.getNode();
18628 EVT VT =
Node->getValueType(0);
18632 Chain =
SP.getValue(1);
18639 Chain = DAG.
getNode(AArch64ISD::PROBED_ALLOCA,
DL, MVT::Other, Chain, SP);
18645AArch64TargetLowering::LowerDYNAMIC_STACKALLOC(
SDValue Op,
18649 if (Subtarget->isTargetWindows())
18650 return LowerWindowsDYNAMIC_STACKALLOC(
Op, DAG);
18652 return LowerInlineDYNAMIC_STACKALLOC(
Op, DAG);
18658 unsigned NewOp)
const {
18659 if (Subtarget->hasSVE2())
18660 return LowerToPredicatedOp(
Op, DAG, NewOp);
18668 EVT VT =
Op.getValueType();
18669 assert(VT != MVT::i64 &&
"Expected illegal VSCALE node");
18672 APInt MulImm =
Op.getConstantOperandAPInt(0);
18678template <
unsigned NumVecs>
18688 for (
unsigned I = 0;
I < NumVecs; ++
I)
18703 if (!Pred || !Pred->isAllOnesValue())
18705 Info.align.reset();
18716 auto &
DL =
I.getDataLayout();
18718 case Intrinsic::aarch64_sve_st2:
18719 case Intrinsic::aarch64_sve_st2q:
18723 case Intrinsic::aarch64_sve_st3:
18724 case Intrinsic::aarch64_sve_st3q:
18728 case Intrinsic::aarch64_sve_st4:
18729 case Intrinsic::aarch64_sve_st4q:
18733 case Intrinsic::aarch64_neon_ld2:
18734 case Intrinsic::aarch64_neon_ld3:
18735 case Intrinsic::aarch64_neon_ld4:
18736 case Intrinsic::aarch64_neon_ld1x2:
18737 case Intrinsic::aarch64_neon_ld1x3:
18738 case Intrinsic::aarch64_neon_ld1x4: {
18740 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
18742 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
18744 Info.align.reset();
18750 case Intrinsic::aarch64_neon_ld2lane:
18751 case Intrinsic::aarch64_neon_ld3lane:
18752 case Intrinsic::aarch64_neon_ld4lane:
18753 case Intrinsic::aarch64_neon_ld2r:
18754 case Intrinsic::aarch64_neon_ld3r:
18755 case Intrinsic::aarch64_neon_ld4r: {
18758 Type *RetTy =
I.getType();
18760 unsigned NumElts = StructTy->getNumElements();
18761 Type *VecTy = StructTy->getElementType(0);
18764 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
18766 Info.align.reset();
18772 case Intrinsic::aarch64_neon_st2:
18773 case Intrinsic::aarch64_neon_st3:
18774 case Intrinsic::aarch64_neon_st4:
18775 case Intrinsic::aarch64_neon_st1x2:
18776 case Intrinsic::aarch64_neon_st1x3:
18777 case Intrinsic::aarch64_neon_st1x4: {
18779 unsigned NumElts = 0;
18780 for (
const Value *Arg :
I.args()) {
18781 Type *ArgTy = Arg->getType();
18784 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
18787 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
18789 Info.align.reset();
18795 case Intrinsic::aarch64_neon_st2lane:
18796 case Intrinsic::aarch64_neon_st3lane:
18797 case Intrinsic::aarch64_neon_st4lane: {
18799 unsigned NumElts = 0;
18801 Type *VecTy =
I.getArgOperand(0)->getType();
18804 for (
const Value *Arg :
I.args()) {
18805 Type *ArgTy = Arg->getType();
18812 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
18814 Info.align.reset();
18820 case Intrinsic::aarch64_ldaxr:
18821 case Intrinsic::aarch64_ldxr: {
18822 Type *ValTy =
I.getParamElementType(0);
18825 Info.ptrVal =
I.getArgOperand(0);
18827 Info.align =
DL.getABITypeAlign(ValTy);
18832 case Intrinsic::aarch64_stlxr:
18833 case Intrinsic::aarch64_stxr: {
18834 Type *ValTy =
I.getParamElementType(1);
18837 Info.ptrVal =
I.getArgOperand(1);
18839 Info.align =
DL.getABITypeAlign(ValTy);
18844 case Intrinsic::aarch64_ldaxp:
18845 case Intrinsic::aarch64_ldxp:
18847 Info.memVT = MVT::i128;
18848 Info.ptrVal =
I.getArgOperand(0);
18850 Info.align =
Align(16);
18854 case Intrinsic::aarch64_stlxp:
18855 case Intrinsic::aarch64_stxp:
18857 Info.memVT = MVT::i128;
18858 Info.ptrVal =
I.getArgOperand(2);
18860 Info.align =
Align(16);
18864 case Intrinsic::aarch64_sve_ldnt1: {
18868 Info.ptrVal =
I.getArgOperand(1);
18870 Info.align =
DL.getABITypeAlign(ElTy);
18875 case Intrinsic::aarch64_sve_stnt1: {
18879 Info.memVT =
MVT::getVT(
I.getOperand(0)->getType());
18880 Info.ptrVal =
I.getArgOperand(2);
18882 Info.align =
DL.getABITypeAlign(ElTy);
18887 case Intrinsic::aarch64_mops_memset_tag: {
18888 Value *Dst =
I.getArgOperand(0);
18889 Value *Val =
I.getArgOperand(1);
18894 Info.align =
I.getParamAlign(0).valueOrOne();
18908 std::optional<unsigned> ByteOffset)
const {
18925 Base.getOperand(1).hasOneUse() &&
18932 uint64_t ShiftAmount =
Base.getOperand(1).getConstantOperandVal(1);
18934 if (ShiftAmount ==
Log2_32(LoadBytes))
18944 if ((VT == MVT::i64 || VT == MVT::i32) && Extend->
use_size()) {
18963 return NumBits1 > NumBits2;
18970 return NumBits1 > NumBits2;
18977 if (
I->getOpcode() != Instruction::FMul)
18980 if (!
I->hasOneUse())
18985 if (!(
User->getOpcode() == Instruction::FSub ||
18986 User->getOpcode() == Instruction::FAdd))
18995 I->getFastMathFlags().allowContract());
19005 return NumBits1 == 32 && NumBits2 == 64;
19012 return NumBits1 == 32 && NumBits2 == 64;
19030bool AArch64TargetLowering::isExtFreeImpl(
const Instruction *Ext)
const {
19038 for (
const Use &U : Ext->
uses()) {
19046 switch (Instr->getOpcode()) {
19047 case Instruction::Shl:
19051 case Instruction::GetElementPtr: {
19054 std::advance(GTI, U.getOperandNo()-1);
19062 uint64_t ShiftAmt =
19067 if (ShiftAmt == 0 || ShiftAmt > 4)
19071 case Instruction::Trunc:
19088 unsigned NumElts,
bool IsLittleEndian,
19090 if (DstWidth % 8 != 0 || DstWidth <= 16 || DstWidth > 64)
19093 assert(DstWidth % SrcWidth == 0 &&
19094 "TBL lowering is not supported for a conversion instruction with this "
19095 "source and destination element type.");
19097 unsigned Factor = DstWidth / SrcWidth;
19098 unsigned MaskLen = NumElts * Factor;
19101 Mask.resize(MaskLen, NumElts);
19103 unsigned SrcIndex = 0;
19104 for (
unsigned I = IsLittleEndian ? 0 : Factor - 1;
I < MaskLen;
I += Factor)
19105 Mask[
I] = SrcIndex++;
19113 bool IsLittleEndian) {
19115 unsigned NumElts = SrcTy->getNumElements();
19123 auto *FirstEltZero = Builder.CreateInsertElement(
19125 Value *Result = Builder.CreateShuffleVector(
Op, FirstEltZero, Mask);
19126 Result = Builder.CreateBitCast(Result, DstTy);
19127 if (DstTy != ZExtTy)
19128 Result = Builder.CreateZExt(Result, ZExtTy);
19134 bool IsLittleEndian) {
19141 !IsLittleEndian, Mask))
19144 auto *FirstEltZero = Builder.CreateInsertElement(
19147 return Builder.CreateShuffleVector(
Op, FirstEltZero, Mask);
19156 assert(SrcTy->getElementType()->isIntegerTy() &&
19157 "Non-integer type source vector element is not supported");
19158 assert(DstTy->getElementType()->isIntegerTy(8) &&
19159 "Unsupported destination vector element type");
19160 unsigned SrcElemTySz =
19162 unsigned DstElemTySz =
19164 assert((SrcElemTySz % DstElemTySz == 0) &&
19165 "Cannot lower truncate to tbl instructions for a source element size "
19166 "that is not divisible by the destination element size");
19167 unsigned TruncFactor = SrcElemTySz / DstElemTySz;
19168 assert((SrcElemTySz == 16 || SrcElemTySz == 32 || SrcElemTySz == 64) &&
19169 "Unsupported source vector element type size");
19177 for (
int Itr = 0; Itr < 16; Itr++) {
19178 if (Itr < NumElements)
19180 IsLittleEndian ? Itr * TruncFactor
19181 : Itr * TruncFactor + (TruncFactor - 1)));
19183 MaskConst.
push_back(Builder.getInt8(255));
19186 int MaxTblSz = 128 * 4;
19187 int MaxSrcSz = SrcElemTySz * NumElements;
19189 (MaxTblSz > MaxSrcSz) ? NumElements : (MaxTblSz / SrcElemTySz);
19190 assert(ElemsPerTbl <= 16 &&
19191 "Maximum elements selected using TBL instruction cannot exceed 16!");
19193 int ShuffleCount = 128 / SrcElemTySz;
19195 for (
int i = 0; i < ShuffleCount; ++i)
19202 while (ShuffleLanes.
back() < NumElements) {
19204 Builder.CreateShuffleVector(TI->
getOperand(0), ShuffleLanes), VecTy));
19206 if (Parts.
size() == 4) {
19209 Builder.CreateIntrinsic(Intrinsic::aarch64_neon_tbl4, VecTy, Parts));
19213 for (
int i = 0; i < ShuffleCount; ++i)
19214 ShuffleLanes[i] += ShuffleCount;
19218 "Lowering trunc for vectors requiring different TBL instructions is "
19222 if (!Parts.
empty()) {
19224 switch (Parts.
size()) {
19226 TblID = Intrinsic::aarch64_neon_tbl1;
19229 TblID = Intrinsic::aarch64_neon_tbl2;
19232 TblID = Intrinsic::aarch64_neon_tbl3;
19237 Results.push_back(Builder.CreateIntrinsic(TblID, VecTy, Parts));
19242 assert(
Results.size() <= 2 &&
"Trunc lowering does not support generation of "
19243 "more than 2 tbl instructions!");
19246 if (ElemsPerTbl < 16) {
19248 std::iota(FinalMask.
begin(), FinalMask.
end(), 0);
19249 FinalResult = Builder.CreateShuffleVector(
Results[0], FinalMask);
19253 if (ElemsPerTbl < 16) {
19254 std::iota(FinalMask.
begin(), FinalMask.
begin() + ElemsPerTbl, 0);
19255 std::iota(FinalMask.
begin() + ElemsPerTbl, FinalMask.
end(), 16);
19257 std::iota(FinalMask.
begin(), FinalMask.
end(), 0);
19271 if (!
EnableExtToTBL || Subtarget->useSVEForFixedLengthVectors())
19279 if (!L || L->getHeader() !=
I->getParent() ||
F->hasOptSize())
19284 if (!SrcTy || !DstTy)
19291 if (ZExt && SrcTy->getElementType()->isIntegerTy(8)) {
19292 auto DstWidth = DstTy->getElementType()->getScalarSizeInBits();
19293 if (DstWidth % 8 != 0)
19296 auto *TruncDstType =
19300 auto SrcWidth = SrcTy->getElementType()->getScalarSizeInBits();
19301 if (
TTI.getCastInstrCost(
I->getOpcode(), DstTy, TruncDstType,
19304 if (SrcWidth * 2 >= TruncDstType->getElementType()->getScalarSizeInBits())
19307 DstTy = TruncDstType;
19315 if (SrcWidth * 4 <= DstWidth) {
19316 if (
all_of(
I->users(), [&](
auto *U) {
19317 using namespace llvm::PatternMatch;
19318 auto *SingleUser = cast<Instruction>(&*U);
19319 if (match(SingleUser, m_c_Mul(m_Specific(I), m_SExt(m_Value()))))
19321 if (match(SingleUser,
19322 m_Intrinsic<Intrinsic::vector_partial_reduce_add>(
19323 m_Value(), m_Specific(I))))
19330 if (DstTy->getScalarSizeInBits() >= 64)
19336 DstTy, Subtarget->isLittleEndian());
19339 ZExt->replaceAllUsesWith(Result);
19340 ZExt->eraseFromParent();
19345 if (UIToFP && ((SrcTy->getElementType()->isIntegerTy(8) &&
19346 DstTy->getElementType()->isFloatTy()) ||
19347 (SrcTy->getElementType()->isIntegerTy(16) &&
19348 DstTy->getElementType()->isDoubleTy()))) {
19353 assert(ZExt &&
"Cannot fail for the i8 to float conversion");
19354 auto *UI = Builder.CreateUIToFP(ZExt, DstTy);
19355 I->replaceAllUsesWith(UI);
19356 I->eraseFromParent();
19361 if (SIToFP && SrcTy->getElementType()->isIntegerTy(8) &&
19362 DstTy->getElementType()->isFloatTy()) {
19366 Subtarget->isLittleEndian());
19367 assert(Shuffle &&
"Cannot fail for the i8 to float conversion");
19369 auto *AShr = Builder.CreateAShr(Cast, 24,
"",
true);
19370 auto *
SI = Builder.CreateSIToFP(AShr, DstTy);
19371 I->replaceAllUsesWith(
SI);
19372 I->eraseFromParent();
19380 (SrcTy->getNumElements() == 8 || SrcTy->getNumElements() == 16) &&
19381 SrcTy->getElementType()->isFloatTy() &&
19382 DstTy->getElementType()->isIntegerTy(8)) {
19384 auto *WideConv = Builder.CreateFPToUI(FPToUI->getOperand(0),
19386 auto *TruncI = Builder.CreateTrunc(WideConv, DstTy);
19387 I->replaceAllUsesWith(TruncI);
19388 I->eraseFromParent();
19398 if (TI && DstTy->getElementType()->isIntegerTy(8) &&
19399 ((SrcTy->getElementType()->isIntegerTy(32) ||
19400 SrcTy->getElementType()->isIntegerTy(64)) &&
19401 (SrcTy->getNumElements() == 16 || SrcTy->getNumElements() == 8))) {
19410 Align &RequiredAlignment)
const {
19415 RequiredAlignment =
Align(1);
19417 return NumBits == 32 || NumBits == 64;
19424 unsigned VecSize = 128;
19428 VecSize = std::max(Subtarget->getMinSVEVectorSizeInBits(), 128u);
19429 return std::max<unsigned>(1, (MinElts * ElSize + 127) / VecSize);
19434 if (Subtarget->getProcFamily() == AArch64Subtarget::Falkor &&
19444 unsigned MinElts = EC.getKnownMinValue();
19446 UseScalable =
false;
19449 (!Subtarget->useSVEForFixedLengthVectors() ||
19454 !Subtarget->isSVEorStreamingSVEAvailable())
19462 if (ElSize != 8 && ElSize != 16 && ElSize != 32 && ElSize != 64)
19465 if (EC.isScalable()) {
19466 UseScalable =
true;
19467 return isPowerOf2_32(MinElts) && (MinElts * ElSize) % 128 == 0;
19470 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
19471 if (Subtarget->useSVEForFixedLengthVectors()) {
19472 unsigned MinSVEVectorSize =
19473 std::max(Subtarget->getMinSVEVectorSizeInBits(), 128u);
19474 if (VecSize % MinSVEVectorSize == 0 ||
19476 (!Subtarget->isNeonAvailable() || VecSize > 128))) {
19477 UseScalable =
true;
19484 return Subtarget->isNeonAvailable() && (VecSize == 64 || VecSize % 128 == 0);
19516 bool Scalable,
Type *LDVTy,
19518 assert(Factor >= 2 && Factor <= 4 &&
"Invalid interleave factor");
19519 static const Intrinsic::ID SVELoads[3] = {Intrinsic::aarch64_sve_ld2_sret,
19520 Intrinsic::aarch64_sve_ld3_sret,
19521 Intrinsic::aarch64_sve_ld4_sret};
19522 static const Intrinsic::ID NEONLoads[3] = {Intrinsic::aarch64_neon_ld2,
19523 Intrinsic::aarch64_neon_ld3,
19524 Intrinsic::aarch64_neon_ld4};
19534 bool Scalable,
Type *STVTy,
19536 assert(Factor >= 2 && Factor <= 4 &&
"Invalid interleave factor");
19537 static const Intrinsic::ID SVEStores[3] = {Intrinsic::aarch64_sve_st2,
19538 Intrinsic::aarch64_sve_st3,
19539 Intrinsic::aarch64_sve_st4};
19540 static const Intrinsic::ID NEONStores[3] = {Intrinsic::aarch64_neon_st2,
19541 Intrinsic::aarch64_neon_st3,
19542 Intrinsic::aarch64_neon_st4};
19566 "Invalid interleave factor");
19567 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
19569 "Unmatched number of shufflevectors and indices");
19574 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
19593 SI->getType()->getScalarSizeInBits() * 4 ==
19594 SI->user_back()->getType()->getScalarSizeInBits();
19604 Type *EltTy = FVTy->getElementType();
19612 FVTy->getNumElements() / NumLoads);
19620 Value *BaseAddr = LI->getPointerOperand();
19622 Type *PtrTy = LI->getPointerOperandType();
19624 LDVTy->getElementCount());
19627 UseScalable, LDVTy, PtrTy);
19634 Value *PTrue =
nullptr;
19636 if (
DL.getTypeSizeInBits(FVTy) != Subtarget->getSVEVectorSizeInBits()) {
19637 std::optional<unsigned> PgPattern =
19639 PTrue = Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue, PredTy,
19640 Builder.getInt32(*PgPattern));
19645 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
19650 BaseAddr = Builder.CreateConstGEP1_32(LDVTy->getElementType(), BaseAddr,
19651 FVTy->getNumElements() * Factor);
19655 LdN = Builder.CreateCall(LdNFunc, {PTrue, BaseAddr},
"ldN");
19657 LdN = Builder.CreateCall(LdNFunc, BaseAddr,
"ldN");
19660 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
19662 unsigned Index = Indices[i];
19664 Value *SubVec = Builder.CreateExtractValue(LdN, Index);
19667 SubVec = Builder.CreateExtractVector(FVTy, SubVec,
uint64_t(0));
19671 SubVec = Builder.CreateIntToPtr(
19673 FVTy->getNumElements()));
19675 SubVecs[SVI].push_back(SubVec);
19684 auto &SubVec = SubVecs[SVI];
19687 SVI->replaceAllUsesWith(WideVec);
19693template <
typename Iter>
19695 int MaxLookupDist = 20;
19696 unsigned IdxWidth =
DL.getIndexSizeInBits(0);
19697 APInt OffsetA(IdxWidth, 0), OffsetB(IdxWidth, 0);
19698 const Value *PtrA1 =
19702 while (++It != End) {
19703 if (It->isDebugOrPseudoInst())
19705 if (MaxLookupDist-- == 0)
19708 const Value *PtrB1 =
19709 SI->getPointerOperand()->stripAndAccumulateConstantOffsets(
19710 DL, OffsetB,
true);
19711 if (PtrA1 == PtrB1 &&
19712 (OffsetA.sextOrTrunc(IdxWidth) - OffsetB.
sextOrTrunc(IdxWidth))
19751 const APInt &GapMask)
const {
19754 "Invalid interleave factor");
19759 "Unexpected mask on store");
19762 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
19764 unsigned LaneLen = VecTy->getNumElements() / Factor;
19765 Type *EltTy = VecTy->getElementType();
19786 Type *IntTy =
DL.getIntPtrType(EltTy);
19787 unsigned NumOpElts =
19792 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
19793 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
19800 LaneLen /= NumStores;
19807 Value *BaseAddr =
SI->getPointerOperand();
19821 if (Factor == 2 && SubVecTy->getPrimitiveSizeInBits() == 64 &&
19840 if (Factor == 2 &&
SI->hasMetadata(LLVMContext::MD_nontemporal) &&
19841 !
F->hasOptSize() && !
F->hasMinSize() &&
19845 Type *PtrTy =
SI->getPointerOperandType();
19847 STVTy->getElementCount());
19850 UseScalable, STVTy, PtrTy);
19852 Value *PTrue =
nullptr;
19854 if (
DL.getTypeSizeInBits(SubVecTy) != Subtarget->getSVEVectorSizeInBits()) {
19855 std::optional<unsigned> PgPattern =
19857 PTrue = Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue, PredTy,
19858 Builder.getInt32(*PgPattern));
19863 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
19868 for (
unsigned i = 0; i < Factor; i++) {
19870 unsigned IdxI = StoreCount * LaneLen * Factor + i;
19871 if (Mask[IdxI] >= 0) {
19872 Shuffle = Builder.CreateShuffleVector(
19875 unsigned StartMask = 0;
19876 for (
unsigned j = 1; j < LaneLen; j++) {
19877 unsigned IdxJ = StoreCount * LaneLen * Factor + j * Factor + i;
19878 if (Mask[IdxJ] >= 0) {
19879 StartMask = Mask[IdxJ] - j;
19888 Shuffle = Builder.CreateShuffleVector(
19896 Ops.push_back(Shuffle);
19900 Ops.push_back(PTrue);
19904 if (StoreCount > 0)
19905 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
19906 BaseAddr, LaneLen * Factor);
19908 Ops.push_back(BaseAddr);
19909 Builder.CreateCall(StNFunc,
Ops);
19916 const APInt &GapMask)
const {
19919 if (Factor != 2 && Factor != 3 && Factor != 4) {
19920 LLVM_DEBUG(
dbgs() <<
"Matching ld2, ld3 and ld4 patterns failed\n");
19926 assert(!Mask &&
"Unexpected mask on a load\n");
19934 const DataLayout &
DL = LI->getModule()->getDataLayout();
19949 Type *PtrTy = LI->getPointerOperandType();
19951 UseScalable, LdTy, PtrTy);
19954 Value *Pred =
nullptr;
19957 Builder.CreateVectorSplat(LdTy->
getElementCount(), Builder.getTrue());
19959 Value *BaseAddr = LI->getPointerOperand();
19960 Value *Result =
nullptr;
19961 if (NumLoads > 1) {
19964 for (
unsigned I = 0;
I < NumLoads; ++
I) {
19968 Value *LdN =
nullptr;
19970 LdN = Builder.CreateCall(LdNFunc, {Pred,
Address},
"ldN");
19972 LdN = Builder.CreateCall(LdNFunc,
Address,
"ldN");
19975 for (
unsigned J = 0; J < Factor; ++J) {
19976 ExtractedLdValues[J] = Builder.CreateInsertVector(
19977 VTy, ExtractedLdValues[J], Builder.CreateExtractValue(LdN, J), Idx);
19984 for (
unsigned J = 0; J < Factor; ++J)
19985 Result = Builder.CreateInsertValue(Result, ExtractedLdValues[J], J);
19988 Result = Builder.CreateCall(LdNFunc, {Pred, BaseAddr},
"ldN");
19990 Result = Builder.CreateCall(LdNFunc, BaseAddr,
"ldN");
20001 unsigned Factor = InterleavedValues.
size();
20002 if (Factor != 2 && Factor != 3 && Factor != 4) {
20003 LLVM_DEBUG(
dbgs() <<
"Matching st2, st3 and st4 patterns failed\n");
20009 assert(!Mask &&
"Unexpected mask on plain store");
20029 Type *PtrTy =
SI->getPointerOperandType();
20031 UseScalable, StTy, PtrTy);
20035 Value *BaseAddr =
SI->getPointerOperand();
20036 Value *Pred =
nullptr;
20040 Builder.CreateVectorSplat(StTy->
getElementCount(), Builder.getTrue());
20042 auto ExtractedValues = InterleavedValues;
20047 for (
unsigned I = 0;
I < NumStores; ++
I) {
20049 if (NumStores > 1) {
20054 for (
unsigned J = 0; J < Factor; J++) {
20056 Builder.CreateExtractVector(StTy, ExtractedValues[J], Idx);
20059 StoreOperands[StoreOperands.
size() - 1] =
Address;
20061 Builder.CreateCall(StNFunc, StoreOperands);
20069 bool CanImplicitFloat = !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat);
20070 bool CanUseNEON = Subtarget->hasNEON() && CanImplicitFloat;
20071 bool CanUseFP = Subtarget->hasFPARMv8() && CanImplicitFloat;
20076 bool IsSmallZeroMemset =
Op.isMemset() &&
Op.size() < 32 &&
Op.isZeroMemset();
20077 auto AlignmentIsAcceptable = [&](
EVT VT,
Align AlignCheck) {
20078 if (
Op.isAligned(AlignCheck))
20088 if (CanUseNEON &&
Op.isMemset() && !IsSmallZeroMemset &&
20089 AlignmentIsAcceptable(MVT::v16i8,
Align(1)))
20091 if (CanUseFP && !IsSmallZeroMemset &&
20092 AlignmentIsAcceptable(MVT::f128,
Align(16)))
20094 if (
Op.size() >= 8 && AlignmentIsAcceptable(MVT::i64,
Align(8)))
20096 if (
Op.size() >= 4 && AlignmentIsAcceptable(MVT::i32,
Align(4)))
20102 LLVMContext &Context, std::vector<EVT> &MemOps,
unsigned Limit,
20103 const MemOp &
Op,
unsigned DstAS,
unsigned SrcAS,
20108 if (VT == MVT::v16i8 &&
Op.isMemset() && !
Op.isZeroMemset() &&
20110 unsigned Size =
Op.size();
20111 unsigned RemainingSize =
Size;
20117 while (RemainingSize > 0) {
20121 if (RemainingSize >= 8) {
20122 TargetVT = MVT::i64;
20123 RemainingSize -= 8;
20124 }
else if (RemainingSize >= 4) {
20125 TargetVT = MVT::i32;
20126 RemainingSize -= 4;
20127 }
else if (RemainingSize >= 2) {
20128 TargetVT = MVT::i16;
20129 RemainingSize -= 2;
20130 }
else if (RemainingSize >= 1) {
20131 TargetVT = MVT::i8;
20132 RemainingSize -= 1;
20138 MemOps.push_back(TargetVT);
20144 if (RemainingSize == 0 && !MemOps.empty()) {
20155 Context, MemOps, Limit,
Op, DstAS, SrcAS, FuncAttributes, LargestVT);
20160 bool CanImplicitFloat = !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat);
20161 bool CanUseNEON = Subtarget->hasNEON() && CanImplicitFloat;
20162 bool CanUseFP = Subtarget->hasFPARMv8() && CanImplicitFloat;
20167 bool IsSmallZeroMemset =
Op.isMemset() &&
Op.size() < 32 &&
Op.isZeroMemset();
20168 auto AlignmentIsAcceptable = [&](
EVT VT,
Align AlignCheck) {
20169 if (
Op.isAligned(AlignCheck))
20179 if (CanUseNEON &&
Op.isMemset() && !IsSmallZeroMemset &&
20180 AlignmentIsAcceptable(MVT::v16i8,
Align(1)))
20182 if (CanUseFP && !IsSmallZeroMemset &&
20183 AlignmentIsAcceptable(MVT::f128,
Align(16)))
20185 if (
Op.size() >= 8 && AlignmentIsAcceptable(MVT::i64,
Align(8)))
20187 if (
Op.size() >= 4 && AlignmentIsAcceptable(MVT::i32,
Align(4)))
20194 if (Immed == std::numeric_limits<int64_t>::min()) {
20203 if (!Subtarget->useScalarIncVL())
20222 return std::abs(
Imm / 8) <= 16;
20225 return std::abs(
Imm / 4) <= 16;
20228 return std::abs(
Imm / 2) <= 16;
20255 if (Insn.
size() > 1)
20292 if (AM.
Scale == 1) {
20295 }
else if (AM.
Scale == 2) {
20307 if (Ty->isScalableTy()) {
20313 uint64_t VecNumBytes =
DL.getTypeSizeInBits(Ty).getKnownMinValue() / 8;
20319 uint64_t VecElemNumBytes =
20322 (AM.
Scale == 0 || (uint64_t)AM.
Scale == VecElemNumBytes);
20334 uint64_t NumBytes = 0;
20335 if (Ty->isSized()) {
20336 uint64_t NumBits =
DL.getTypeSizeInBits(Ty);
20337 NumBytes = NumBits / 8;
20342 return Subtarget->getInstrInfo()->isLegalAddressingMode(NumBytes, AM.
BaseOffs,
20350 int64_t MaxOffset)
const {
20351 int64_t HighPart = MinOffset & ~0xfffULL;
20374 return Subtarget->hasFullFP16();
20377 return Subtarget->hasFPARMv8();
20380 (Subtarget->hasBF16() || Subtarget->hasSVEB16B16());
20390 switch (Ty->getScalarType()->getTypeID()) {
20393 return Subtarget->hasFPARMv8();
20410 static const MCPhysReg ScratchRegs[] = {
20411 AArch64::X16, AArch64::X17, AArch64::LR, 0
20413 return ScratchRegs;
20417 static const MCPhysReg RCRegs[] = {AArch64::FPCR};
20422 EVT DestVT)
const {
20431 "Expected shift op");
20433 SDValue ShiftLHS =
N->getOperand(0);
20434 EVT VT =
N->getValueType(0);
20455 return SRLC->getZExtValue() == SHLC->getZExtValue();
20467 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
20468 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
20469 "Expected XOR(SHIFT) pattern");
20474 if (XorC && ShiftC) {
20475 unsigned MaskIdx, MaskLen;
20476 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
20477 unsigned ShiftAmt = ShiftC->getZExtValue();
20478 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
20479 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
20480 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
20481 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
20491 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
20493 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
20494 "Expected shift-shift mask");
20496 if (!
N->getOperand(0)->hasOneUse())
20500 EVT VT =
N->getValueType(0);
20501 if (
N->getOpcode() ==
ISD::SRL && (VT == MVT::i32 || VT == MVT::i64)) {
20504 return (!C1 || !C2 || C1->getZExtValue() >= C2->getZExtValue());
20509 if (
N->getOpcode() ==
ISD::SHL &&
N->hasOneUse()) {
20511 unsigned ShlAmt = C2->getZExtValue();
20512 if (
auto ShouldADD = *
N->user_begin();
20513 ShouldADD->getOpcode() ==
ISD::ADD && ShouldADD->hasOneUse()) {
20515 EVT MemVT =
Load->getMemoryVT();
20517 if (
Load->getValueType(0).isScalableVector())
20531 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
20539 assert(Ty->isIntegerTy());
20541 unsigned BitSize = Ty->getPrimitiveSizeInBits();
20545 int64_t Val =
Imm.getSExtValue();
20552 Val &= (1LL << 32) - 1;
20561 unsigned Index)
const {