83#include "llvm/IR/IntrinsicsARM.h"
118#define DEBUG_TYPE "arm-isel"
121STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
122STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
124 "Number of constants with their storage promoted into constant pools");
128 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
133 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
138 cl::desc(
"Maximum size of constant to promote into a constant pool"),
142 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
147 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
152 cl::desc(
"Maximum number of base-updates to check generating postindex."),
160 ARM::R0, ARM::R1, ARM::R2, ARM::R3
174void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
175 if (VT != PromotedLdStVT) {
184 if (ElemTy != MVT::f64)
188 if (ElemTy == MVT::i32) {
232void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
234 addTypeForNEON(VT, MVT::f64);
237void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
239 addTypeForNEON(VT, MVT::v2f64);
242void ARMTargetLowering::setAllExpand(
MVT VT) {
255void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
262void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
263 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
265 for (
auto VT : IntTypes) {
339 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
340 for (
auto VT : FloatTypes) {
414 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
415 for (
auto VT : LongTypes) {
432 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
433 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
434 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
451 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
460 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
461 for (
auto VT : pTypes) {
512 RegInfo(Subtarget->getRegisterInfo()),
513 Itins(Subtarget->getInstrItineraryData()) {
519 const Triple &TT = TM.getTargetTriple();
521 if (TT.isOSBinFormatMachO()) {
523 if (Subtarget->isThumb() && Subtarget->hasVFP2Base() &&
524 Subtarget->hasARMOps() && !Subtarget->useSoftFloat()) {
526 static const struct {
527 const RTLIB::Libcall
Op;
528 const RTLIB::LibcallImpl Impl;
531 { RTLIB::ADD_F32, RTLIB::impl___addsf3vfp },
532 { RTLIB::SUB_F32, RTLIB::impl___subsf3vfp },
533 { RTLIB::MUL_F32, RTLIB::impl___mulsf3vfp },
534 { RTLIB::DIV_F32, RTLIB::impl___divsf3vfp },
537 { RTLIB::ADD_F64, RTLIB::impl___adddf3vfp },
538 { RTLIB::SUB_F64, RTLIB::impl___subdf3vfp },
539 { RTLIB::MUL_F64, RTLIB::impl___muldf3vfp },
540 { RTLIB::DIV_F64, RTLIB::impl___divdf3vfp },
543 { RTLIB::OEQ_F32, RTLIB::impl___eqsf2vfp },
544 { RTLIB::UNE_F32, RTLIB::impl___nesf2vfp },
545 { RTLIB::OLT_F32, RTLIB::impl___ltsf2vfp },
546 { RTLIB::OLE_F32, RTLIB::impl___lesf2vfp },
547 { RTLIB::OGE_F32, RTLIB::impl___gesf2vfp },
548 { RTLIB::OGT_F32, RTLIB::impl___gtsf2vfp },
549 { RTLIB::UO_F32, RTLIB::impl___unordsf2vfp },
552 { RTLIB::OEQ_F64, RTLIB::impl___eqdf2vfp },
553 { RTLIB::UNE_F64, RTLIB::impl___nedf2vfp },
554 { RTLIB::OLT_F64, RTLIB::impl___ltdf2vfp },
555 { RTLIB::OLE_F64, RTLIB::impl___ledf2vfp },
556 { RTLIB::OGE_F64, RTLIB::impl___gedf2vfp },
557 { RTLIB::OGT_F64, RTLIB::impl___gtdf2vfp },
558 { RTLIB::UO_F64, RTLIB::impl___unorddf2vfp },
563 { RTLIB::FPTOSINT_F64_I32, RTLIB::impl___fixdfsivfp },
564 { RTLIB::FPTOUINT_F64_I32, RTLIB::impl___fixunsdfsivfp },
565 { RTLIB::FPTOSINT_F32_I32, RTLIB::impl___fixsfsivfp },
566 { RTLIB::FPTOUINT_F32_I32, RTLIB::impl___fixunssfsivfp },
569 { RTLIB::FPROUND_F64_F32, RTLIB::impl___truncdfsf2vfp },
570 { RTLIB::FPEXT_F32_F64, RTLIB::impl___extendsfdf2vfp },
577 { RTLIB::SINTTOFP_I32_F64, RTLIB::impl___floatsidfvfp },
578 { RTLIB::UINTTOFP_I32_F64, RTLIB::impl___floatunssidfvfp },
579 { RTLIB::SINTTOFP_I32_F32, RTLIB::impl___floatsisfvfp },
580 { RTLIB::UINTTOFP_I32_F32, RTLIB::impl___floatunssisfvfp },
584 for (
const auto &LC : LibraryCalls)
589 if (Subtarget->isThumb1Only())
594 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
595 Subtarget->hasFPRegs()) {
604 if (!Subtarget->hasVFP2Base()) {
605 setAllExpand(MVT::f32);
611 if (!Subtarget->hasFP64()) {
612 setAllExpand(MVT::f64);
620 if (Subtarget->hasFullFP16()) {
629 if (Subtarget->hasBF16()) {
631 setAllExpand(MVT::bf16);
632 if (!Subtarget->hasFullFP16())
644 addAllExtLoads(VT, InnerVT,
Expand);
653 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
656 if (!Subtarget->hasV8_1MMainlineOps())
659 if (!Subtarget->isThumb1Only())
668 if (Subtarget->hasMVEIntegerOps())
669 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
672 if (Subtarget->hasLOB()) {
676 if (Subtarget->hasNEON()) {
677 addDRTypeForNEON(MVT::v2f32);
678 addDRTypeForNEON(MVT::v8i8);
679 addDRTypeForNEON(MVT::v4i16);
680 addDRTypeForNEON(MVT::v2i32);
681 addDRTypeForNEON(MVT::v1i64);
683 addQRTypeForNEON(MVT::v4f32);
684 addQRTypeForNEON(MVT::v2f64);
685 addQRTypeForNEON(MVT::v16i8);
686 addQRTypeForNEON(MVT::v8i16);
687 addQRTypeForNEON(MVT::v4i32);
688 addQRTypeForNEON(MVT::v2i64);
690 if (Subtarget->hasFullFP16()) {
691 addQRTypeForNEON(MVT::v8f16);
692 addDRTypeForNEON(MVT::v4f16);
695 if (Subtarget->hasBF16()) {
696 addQRTypeForNEON(MVT::v8bf16);
697 addDRTypeForNEON(MVT::v4bf16);
701 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
741 if (Subtarget->hasNEON()) {
782 ISD::FRINT, ISD::FTRUNC, ISD::FROUNDEVEN}) {
854 if (!Subtarget->hasVFP4Base()) {
863 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
872 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
881 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
889 if (Subtarget->hasMVEIntegerOps()) {
894 if (Subtarget->hasMVEFloatOps()) {
898 if (!Subtarget->hasFP64()) {
943 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
946 if (Subtarget->hasFullFP16()) {
952 if (!Subtarget->hasFP16()) {
978 if (!Subtarget->isThumb1Only()) {
1003 if (Subtarget->hasDSP()) {
1013 if (Subtarget->hasBaseDSP()) {
1021 if (Subtarget->isThumb1Only()) {
1025 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
1026 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1041 if (Subtarget->hasMVEIntegerOps())
1045 if (Subtarget->isThumb1Only()) {
1051 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1065 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1074 if (Subtarget->hasPerfMon())
1078 if (!Subtarget->hasV6Ops())
1081 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1082 : Subtarget->hasDivideInARMMode();
1089 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1101 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1102 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1105 HasStandaloneRem =
false;
1132 if (TT.isOSWindows())
1139 InsertFencesForAtomic =
false;
1140 if (Subtarget->hasAnyDataBarrier() &&
1141 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1145 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1150 if (!Subtarget->hasAcquireRelease() ||
1153 InsertFencesForAtomic =
true;
1159 if (Subtarget->hasDataBarrier())
1160 InsertFencesForAtomic =
true;
1180 if (!InsertFencesForAtomic) {
1187 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1199 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1200 Subtarget->hasForced32BitAtomics()) {
1214 if (!Subtarget->hasV6Ops()) {
1220 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1221 !Subtarget->isThumb1Only()) {
1250 if (Subtarget->hasFullFP16()) {
1260 if (Subtarget->hasFullFP16())
1275 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1276 !Subtarget->isThumb1Only()) {
1283 if (!Subtarget->hasVFP4Base()) {
1289 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1291 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1299 if (!Subtarget->hasFP16()) {
1319 if (Subtarget->hasFPARMv8Base()) {
1329 if (Subtarget->hasNEON()) {
1336 if (Subtarget->hasFP64()) {
1351 if (Subtarget->hasFullFP16()) {
1357 ISD::FCOS, ISD::FSIN, ISD::FSINCOS,
1358 ISD::FSINCOSPI, ISD::FMODF, ISD::FACOS,
1359 ISD::FASIN, ISD::FATAN, ISD::FATAN2,
1360 ISD::FCOSH, ISD::FSINH, ISD::FTANH,
1361 ISD::FTAN, ISD::FEXP, ISD::FEXP2,
1362 ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
1378 for (
auto Op : {ISD::FROUND, ISD::FROUNDEVEN, ISD::FTRUNC,
1379 ISD::FNEARBYINT, ISD::FRINT, ISD::FFLOOR,
1388 if (Subtarget->hasNEON()) {
1400 if (Subtarget->hasV8Ops()) {
1415 if (Subtarget->hasFullFP16()) {
1443 if (TT.isOSWindows()) {
1460 if (Subtarget->hasMVEIntegerOps())
1463 if (Subtarget->hasV6Ops())
1465 if (Subtarget->isThumb1Only())
1468 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1469 Subtarget->isThumb2()) {
1475 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1476 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1498 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1504 return Subtarget->useSoftFloat();
1508 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1521std::pair<const TargetRegisterClass *, uint8_t>
1532 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1533 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1534 RRC = &ARM::DPRRegClass;
1539 if (Subtarget->useNEONForSinglePrecisionFP())
1542 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1543 case MVT::v4f32:
case MVT::v2f64:
1544 RRC = &ARM::DPRRegClass;
1548 RRC = &ARM::DPRRegClass;
1552 RRC = &ARM::DPRRegClass;
1556 return std::make_pair(RRC,
Cost);
1565 if ((Subtarget->hasMVEIntegerOps() &&
1566 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1567 VT == MVT::v16i8)) ||
1568 (Subtarget->hasMVEFloatOps() &&
1569 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1583 if (Subtarget->hasNEON()) {
1584 if (VT == MVT::v4i64)
1585 return &ARM::QQPRRegClass;
1586 if (VT == MVT::v8i64)
1587 return &ARM::QQQQPRRegClass;
1589 if (Subtarget->hasMVEIntegerOps()) {
1590 if (VT == MVT::v4i64)
1591 return &ARM::MQQPRRegClass;
1592 if (VT == MVT::v8i64)
1593 return &ARM::MQQQQPRRegClass;
1602 Align &PrefAlign)
const {
1609 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1621 unsigned NumVals =
N->getNumValues();
1625 for (
unsigned i = 0; i != NumVals; ++i) {
1626 EVT VT =
N->getValueType(i);
1627 if (VT == MVT::Glue || VT == MVT::Other)
1633 if (!
N->isMachineOpcode())
1641 if (
MCID.getNumDefs() == 0)
1643 if (!Itins->isEmpty() &&
1644 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1658 return Const->getZExtValue() == 16;
1666 return Const->getZExtValue() == 16;
1674 return Const->getZExtValue() == 16;
1743 bool isVarArg)
const {
1762 if (!
getTM().isAAPCS_ABI())
1764 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1772 if (!
getTM().isAAPCS_ABI()) {
1773 if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() && !isVarArg)
1776 }
else if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() &&
1785 bool isVarArg)
const {
1786 return CCAssignFnForNode(CC,
false, isVarArg);
1790 bool isVarArg)
const {
1791 return CCAssignFnForNode(CC,
true, isVarArg);
1798 bool isVarArg)
const {
1799 switch (getEffectiveCallingConv(CC, isVarArg)) {
1825 if (Subtarget->hasFullFP16()) {
1826 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1830 Val = DAG.
getNode(ISD::BITCAST, dl, ValVT, Val);
1838 if (Subtarget->hasFullFP16()) {
1839 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1842 Val = DAG.
getNode(ISD::BITCAST, dl,
1847 return DAG.
getNode(ISD::BITCAST, dl, LocVT, Val);
1852SDValue ARMTargetLowering::LowerCallResult(
1856 SDValue ThisVal,
bool isCmseNSCall)
const {
1864 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1865 CCValAssign VA = RVLocs[i];
1869 if (i == 0 && isThisReturn) {
1871 "unexpected return calling convention register assignment");
1889 if (!Subtarget->isLittle())
1891 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1906 if (!Subtarget->isLittle())
1908 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1949std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1951 bool IsTailCall,
int SPDiff)
const {
1953 MachinePointerInfo DstInfo;
1973 return std::make_pair(DstAddr, DstInfo);
1982ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1995 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1998 int SrcFI = SrcFrameIdxNode->getIndex();
1999 int DstFI = DstFrameIdxNode->getIndex();
2001 "byval passed in non-fixed stack slot");
2023 if (SrcOffset == DstOffset)
2031 RegsToPassVector &RegsToPass,
2038 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
2039 unsigned id = Subtarget->isLittle() ? 0 : 1;
2051 MachinePointerInfo DstInfo;
2052 std::tie(DstAddr, DstInfo) =
2053 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2070 SelectionDAG &DAG = CLI.
DAG;
2072 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2073 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2074 SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2081 const CallBase *CB = CLI.
CB;
2084 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2086 MachineFunction::CallSiteInfo CSInfo;
2087 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2088 bool isThisReturn =
false;
2089 bool isCmseNSCall =
false;
2090 bool isSibCall =
false;
2091 bool PreferIndirect =
false;
2092 bool GuardWithBTI =
false;
2102 !Subtarget->noBTIAtReturnTwice())
2107 CSInfo = MachineFunction::CallSiteInfo(*CB);
2111 isCmseNSCall =
true;
2114 if (!Subtarget->supportsTailCall())
2130 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2131 count_if(GV->users(), [&BB](
const User *U) {
2132 return isa<Instruction>(U) &&
2133 cast<Instruction>(U)->getParent() == BB;
2140 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2154 "site marked musttail");
2157 unsigned NumBytes = CCInfo.getStackSize();
2166 if (isTailCall && !isSibCall) {
2167 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2168 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2173 assert(StackAlign &&
"data layout string is missing stack alignment");
2174 NumBytes =
alignTo(NumBytes, *StackAlign);
2179 SPDiff = NumReusableBytes - NumBytes;
2183 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2199 RegsToPassVector RegsToPass;
2208 DenseMap<unsigned, SDValue> ByValTemporaries;
2212 for (
const CCValAssign &VA : ArgLocs) {
2214 SDValue Src = OutVals[ArgIdx];
2215 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2217 if (!
Flags.isByVal())
2221 MachinePointerInfo DstInfo;
2222 std::tie(Dst, DstInfo) =
2223 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2224 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2226 if (Copy == NoCopy) {
2231 }
else if (Copy == CopyOnce) {
2235 ByValTemporaries[ArgIdx] = Src;
2237 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2241 int TempFrameIdx = MFI.CreateStackObject(
2242 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2250 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2251 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2253 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2254 ByValTemporaries[ArgIdx] = Temp;
2257 if (!ByValCopyChains.
empty())
2267 bool AfterFormalArgLoads =
false;
2271 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2273 ++i, ++realArgIdx) {
2274 CCValAssign &VA = ArgLocs[i];
2275 SDValue Arg = OutVals[realArgIdx];
2276 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2277 bool isByVal =
Flags.isByVal();
2297 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2299 if (ByValTempChain) {
2304 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2305 if (Outs[
I].
Flags.isByVal())
2313 FrameIndexSDNode *FIN =
2318 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2321 for (
const CCValAssign &VA : ArgLocs) {
2329 if (!IncomingLoad.
empty()) {
2337 AfterFormalArgLoads =
true;
2349 auto ArgVT = Outs[realArgIdx].ArgVT;
2350 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2368 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2369 StackPtr, MemOpChains, isTailCall, SPDiff);
2373 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2374 StackPtr, MemOpChains, isTailCall, SPDiff);
2378 MachinePointerInfo DstInfo;
2379 std::tie(DstAddr, DstInfo) =
2380 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2384 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2385 StackPtr, MemOpChains, isTailCall, SPDiff);
2387 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2388 Outs[0].VT == MVT::i32) {
2390 "unexpected calling convention register assignment");
2391 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2392 "unexpected use of 'returned'");
2393 isThisReturn =
true;
2398 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2399 }
else if (isByVal) {
2401 unsigned offset = 0;
2405 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2406 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2409 bool NeedsStackCopy;
2410 if (
auto It = ByValTemporaries.
find(realArgIdx);
2411 It != ByValTemporaries.
end()) {
2412 ByValSrc = It->second;
2413 NeedsStackCopy =
true;
2416 NeedsStackCopy = !isTailCall;
2420 if (CurByValIdx < ByValArgsCount) {
2421 unsigned RegBegin, RegEnd;
2422 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2426 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2430 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2433 RegsToPass.push_back(std::make_pair(j, Load));
2438 offset = RegEnd - RegBegin;
2440 CCInfo.nextInRegsParam();
2445 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2448 MachinePointerInfo DstInfo;
2449 std::tie(Dst, DstInfo) =
2450 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2458 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2459 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2466 MachinePointerInfo DstInfo;
2467 std::tie(DstAddr, DstInfo) =
2468 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2475 if (!MemOpChains.
empty())
2481 for (
const auto &[
Reg,
N] : RegsToPass) {
2489 bool isDirect =
false;
2492 const GlobalValue *GVal =
nullptr;
2494 GVal =
G->getGlobal();
2495 bool isStub = !TM.shouldAssumeDSOLocal(GVal) && Subtarget->isTargetMachO();
2497 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2498 bool isLocalARMFunc =
false;
2501 if (Subtarget->genLongCalls()) {
2503 "long-calls codegen is not position independent!");
2508 if (Subtarget->genExecuteOnly()) {
2509 if (Subtarget->useMovt())
2521 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2527 const char *Sym = S->getSymbol();
2529 if (Subtarget->genExecuteOnly()) {
2530 if (Subtarget->useMovt())
2542 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2549 if (!PreferIndirect) {
2554 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2556 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2557 assert(Subtarget->isTargetMachO() &&
"WrapperPIC use on non-MachO?");
2559 ARMISD::WrapperPIC, dl, PtrVt,
2566 }
else if (Subtarget->isTargetCOFF()) {
2567 assert(Subtarget->isTargetWindows() &&
2568 "Windows is the only supported COFF target");
2572 else if (!TM.shouldAssumeDSOLocal(GVal))
2579 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2588 const char *Sym = S->getSymbol();
2589 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2591 ARMConstantPoolValue *CPV =
2593 ARMPCLabelIndex, 4);
2595 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2600 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2607 assert(!isARMFunc && !isDirect &&
2608 "Cannot handle call to ARM function or direct call");
2612 "call to non-secure function would require "
2613 "passing arguments on stack",
2619 "call to non-secure function would return value through pointer",
2626 if (Subtarget->isThumb()) {
2628 CallOpc = ARMISD::t2CALL_BTI;
2629 else if (isCmseNSCall)
2630 CallOpc = ARMISD::tSECALL;
2631 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2632 CallOpc = ARMISD::CALL_NOLINK;
2634 CallOpc = ARMISD::CALL;
2636 if (!isDirect && !Subtarget->hasV5TOps())
2637 CallOpc = ARMISD::CALL_NOLINK;
2638 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2640 !Subtarget->hasMinSize())
2642 CallOpc = ARMISD::CALL_NOLINK;
2644 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2651 if (isTailCall && !isSibCall) {
2656 std::vector<SDValue>
Ops;
2657 Ops.push_back(Chain);
2658 Ops.push_back(Callee);
2666 for (
const auto &[
Reg,
N] : RegsToPass)
2670 const uint32_t *
Mask;
2671 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2679 isThisReturn =
false;
2685 assert(Mask &&
"Missing call preserved mask for calling convention");
2689 Ops.push_back(InGlue);
2702 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2713 uint64_t CalleePopBytes =
2716 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2722 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2723 InVals, isThisReturn,
2724 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2731void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2732 Align Alignment)
const {
2734 Alignment = std::max(Alignment,
Align(4));
2740 unsigned AlignInRegs = Alignment.
value() / 4;
2741 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2742 for (
unsigned i = 0; i < Waste; ++i)
2748 unsigned Excess = 4 * (ARM::R4 -
Reg);
2755 if (NSAAOffset != 0 &&
Size > Excess) {
2767 unsigned ByValRegBegin =
Reg;
2768 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2772 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2778 Size = std::max<int>(
Size - Excess, 0);
2786bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2792 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2793 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2794 const SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2795 const SelectionDAG &DAG = CLI.
DAG;
2800 assert(Subtarget->supportsTailCall());
2813 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2815 if (!(Subtarget->isThumb1Only() ||
2816 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2817 AddressRegisters.
insert(ARM::R12);
2818 for (
const CCValAssign &AL : ArgLocs)
2820 AddressRegisters.
erase(
AL.getLocReg());
2821 if (AddressRegisters.
empty()) {
2822 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2841 <<
" (guaranteed tail-call CC)\n");
2842 return CalleeCC == CallerCC;
2847 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2849 if (isCalleeStructRet != isCallerStructRet) {
2862 const GlobalValue *GV =
G->getGlobal();
2865 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2866 TT.isOSBinFormatMachO())) {
2875 getEffectiveCallingConv(CalleeCC, isVarArg),
2876 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
2883 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2884 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2885 if (CalleeCC != CallerCC) {
2886 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2887 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2896 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2906 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2925 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2934 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2947 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2950 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2954 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2959 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2981 bool isLittleEndian = Subtarget->isLittle();
2984 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2993 "secure entry function would return value through pointer",
2998 for (
unsigned i = 0, realRVLocIdx = 0;
3000 ++i, ++realRVLocIdx) {
3001 CCValAssign &VA = RVLocs[i];
3004 SDValue Arg = OutVals[realRVLocIdx];
3005 bool ReturnF16 =
false;
3007 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
3040 auto RetVT = Outs[realRVLocIdx].ArgVT;
3062 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3066 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3072 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3084 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3086 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3091 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3101 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3127 !Subtarget->isMClass()) {
3128 if (Subtarget->isThumb1Only())
3135 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3138bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3139 if (
N->getNumValues() != 1)
3141 if (!
N->hasNUsesOfValue(1, 0))
3145 SDNode *
Copy = *
N->user_begin();
3149 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3151 TCChain =
Copy->getOperand(0);
3152 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3153 SDNode *VMov =
Copy;
3155 SmallPtrSet<SDNode*, 2>
Copies;
3156 for (SDNode *U : VMov->
users()) {
3164 for (SDNode *U : VMov->
users()) {
3165 SDValue UseChain =
U->getOperand(0);
3173 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3179 }
else if (
Copy->getOpcode() == ISD::BITCAST) {
3181 if (!
Copy->hasOneUse())
3188 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3190 TCChain =
Copy->getOperand(0);
3195 bool HasRet =
false;
3196 for (
const SDNode *U :
Copy->users()) {
3197 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3198 U->getOpcode() != ARMISD::INTRET_GLUE)
3210bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3211 if (!Subtarget->supportsTailCall())
3228 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3244 EVT PtrVT =
Op.getValueType();
3254 if (Subtarget->genExecuteOnly()) {
3256 auto *
T =
CP->getType();
3257 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3259 auto GV =
new GlobalVariable(
3267 return LowerGlobalAddress(GA, DAG);
3272 Align CPAlign =
CP->getAlign();
3273 if (Subtarget->isThumb1Only())
3274 CPAlign = std::max(CPAlign,
Align(4));
3275 if (
CP->isMachineConstantPoolEntry())
3280 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3287 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3296 unsigned ARMPCLabelIndex = 0;
3302 if (!IsPositionIndependent) {
3305 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3312 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3316 if (!IsPositionIndependent)
3319 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3347ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3349 assert(Subtarget->isTargetDarwin() &&
3350 "This function expects a Darwin target");
3355 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3361 MVT::i32,
DL, Chain, DescAddr,
3376 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3385 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3391ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3393 assert(Subtarget->isTargetWindows() &&
"Windows specific TLS lowering");
3417 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3425 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3426 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3432 MachinePointerInfo());
3439 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3452 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3454 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3456 ARMConstantPoolValue *CPV =
3467 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3474 TargetLowering::CallLoweringInfo CLI(DAG);
3479 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3480 return CallResult.first;
3489 const GlobalValue *GV = GA->
getGlobal();
3499 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3502 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3503 ARMConstantPoolValue *CPV =
3510 PtrVT, dl, Chain,
Offset,
3518 PtrVT, dl, Chain,
Offset,
3523 ARMConstantPoolValue *CPV =
3528 PtrVT, dl, Chain,
Offset,
3543 if (Subtarget->isTargetDarwin())
3544 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3546 if (Subtarget->isTargetWindows())
3547 return LowerGlobalTLSAddressWindows(
Op, DAG);
3550 assert(Subtarget->isTargetELF() &&
"Only ELF implemented here");
3556 return LowerToTLSGeneralDynamicModel(GA, DAG);
3559 return LowerToTLSExecModels(GA, DAG, model);
3568 while (!Worklist.
empty()) {
3576 if (!
I ||
I->getParent()->getParent() !=
F)
3605 if (!GVar || !GVar->hasInitializer() ||
3606 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3607 !GVar->hasLocalLinkage())
3612 auto *
Init = GVar->getInitializer();
3614 Init->needsDynamicRelocation())
3626 unsigned RequiredPadding = 4 - (
Size % 4);
3627 bool PaddingPossible =
3628 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3633 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3657 if (RequiredPadding != 4) {
3662 while (RequiredPadding--)
3674 ++NumConstpoolPromoted;
3675 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3680 if (!(GV = GA->getAliaseeObject()))
3683 return V->isConstant();
3692 return LowerGlobalAddressWindows(
Op, DAG);
3694 return LowerGlobalAddressELF(
Op, DAG);
3696 return LowerGlobalAddressDarwin(
Op, DAG);
3708 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3721 }
else if (Subtarget->isROPI() && IsRO) {
3726 }
else if (Subtarget->isRWPI() && !IsRO) {
3729 if (Subtarget->useMovt()) {
3732 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3734 ARMConstantPoolValue *CPV =
3737 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3751 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3752 if (Subtarget->useMovt())
3756 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3760 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3769 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3770 "ROPI/RWPI not currently supported for Darwin");
3775 if (Subtarget->useMovt())
3786 if (Subtarget->isGVIndirectSymbol(GV))
3794 assert(Subtarget->isTargetWindows() &&
"non-Windows COFF is not supported");
3795 assert(Subtarget->useMovt() &&
3796 "Windows on ARM expects to use movw/movt");
3797 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3798 "ROPI/RWPI not currently supported for Windows");
3805 else if (!TM.shouldAssumeDSOLocal(GV))
3828 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3829 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3830 Op.getOperand(1), Val);
3836 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3843 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3847SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3850 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3854 case Intrinsic::arm_gnu_eabi_mcount: {
3860 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3861 const uint32_t *
Mask =
3863 assert(Mask &&
"Missing call preserved mask for calling convention");
3868 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3872 if (Subtarget->isThumb())
3875 ARM::tBL_PUSHLR, dl, ResultTys,
3876 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3877 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3881 {ReturnAddress, Callee, RegisterMask, Chain}),
3890 unsigned IntNo =
Op.getConstantOperandVal(0);
3894 case Intrinsic::thread_pointer: {
3896 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3898 case Intrinsic::arm_cls: {
3899 const SDValue &Operand =
Op.getOperand(1);
3900 const EVT VTy =
Op.getValueType();
3911 case Intrinsic::arm_cls64: {
3914 const SDValue &Operand =
Op.getOperand(1);
3915 const EVT VTy =
Op.getValueType();
3938 case Intrinsic::eh_sjlj_lsda: {
3940 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3945 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3946 ARMConstantPoolValue *CPV =
3950 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3955 if (IsPositionIndependent) {
3957 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3961 case Intrinsic::arm_neon_vabs:
3964 case Intrinsic::arm_neon_vabds:
3965 if (
Op.getValueType().isInteger())
3967 Op.getOperand(1),
Op.getOperand(2));
3969 case Intrinsic::arm_neon_vabdu:
3971 Op.getOperand(1),
Op.getOperand(2));
3972 case Intrinsic::arm_neon_vmulls:
3973 case Intrinsic::arm_neon_vmullu: {
3974 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3975 ? ARMISD::VMULLs : ARMISD::VMULLu;
3976 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3977 Op.getOperand(1),
Op.getOperand(2));
3979 case Intrinsic::arm_neon_vminnm:
3980 case Intrinsic::arm_neon_vmaxnm: {
3981 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3982 ? ISD::FMINNUM : ISD::FMAXNUM;
3983 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3984 Op.getOperand(1),
Op.getOperand(2));
3986 case Intrinsic::arm_neon_vminu:
3987 case Intrinsic::arm_neon_vmaxu: {
3988 if (
Op.getValueType().isFloatingPoint())
3990 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3992 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3993 Op.getOperand(1),
Op.getOperand(2));
3995 case Intrinsic::arm_neon_vmins:
3996 case Intrinsic::arm_neon_vmaxs: {
3998 if (!
Op.getValueType().isFloatingPoint()) {
3999 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4001 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4002 Op.getOperand(1),
Op.getOperand(2));
4004 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4005 ? ISD::FMINIMUM : ISD::FMAXIMUM;
4006 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4007 Op.getOperand(1),
Op.getOperand(2));
4009 case Intrinsic::arm_neon_vtbl1:
4010 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
4011 Op.getOperand(1),
Op.getOperand(2));
4012 case Intrinsic::arm_neon_vtbl2:
4013 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
4014 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4015 case Intrinsic::arm_mve_pred_i2v:
4016 case Intrinsic::arm_mve_pred_v2i:
4017 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
4019 case Intrinsic::arm_mve_vreinterpretq:
4020 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
4022 case Intrinsic::arm_mve_lsll:
4023 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
4024 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4025 case Intrinsic::arm_mve_asrl:
4026 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
4027 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4038 if (!Subtarget->hasDataBarrier()) {
4042 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4043 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4044 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
4054 }
else if (Subtarget->preferISHSTBarriers() &&
4063 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4071 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4073 return Op.getOperand(0);
4076 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4078 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4080 return Op.getOperand(0);
4082 unsigned isData =
Op.getConstantOperandVal(4);
4083 if (Subtarget->isThumb()) {
4085 isRead = ~isRead & 1;
4086 isData = ~isData & 1;
4089 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4104 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4112 const SDLoc &dl)
const {
4114 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4116 const TargetRegisterClass *RC;
4118 RC = &ARM::tGPRRegClass;
4120 RC = &ARM::GPRRegClass;
4134 MVT::i32, dl, Root, FIN,
4140 if (!Subtarget->isLittle())
4142 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4155 const Value *OrigArg,
4156 unsigned InRegsParamRecordIdx,
4157 int ArgOffset,
unsigned ArgSize)
const {
4171 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4172 unsigned RBegin, REnd;
4177 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4182 ArgOffset = -4 * (ARM::R4 - RBegin);
4189 const TargetRegisterClass *RC =
4192 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4196 MachinePointerInfo(OrigArg, 4 * i));
4201 if (!MemOps.
empty())
4210 unsigned TotalArgRegsSaveSize,
4211 bool ForceMutable)
const {
4213 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4222 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4226bool ARMTargetLowering::splitValueIntoRegisterParts(
4228 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4230 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4235 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
4242SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4244 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4245 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4252 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
4258SDValue ARMTargetLowering::LowerFormalArguments(
4265 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4274 unsigned CurArgIdx = 0;
4286 unsigned ArgRegBegin = ARM::R4;
4287 for (
const CCValAssign &VA : ArgLocs) {
4293 if (!
Flags.isByVal())
4297 unsigned RBegin, REnd;
4299 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4305 int lastInsIndex = -1;
4309 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4312 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4316 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4317 CCValAssign &VA = ArgLocs[i];
4318 if (Ins[VA.
getValNo()].isOrigArg()) {
4319 std::advance(CurOrigArg,
4320 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4332 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4339 MVT::f64, dl, Chain, FIN,
4342 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4350 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4352 const TargetRegisterClass *RC;
4354 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4355 RC = &ARM::HPRRegClass;
4356 else if (RegVT == MVT::f32)
4357 RC = &ARM::SPRRegClass;
4358 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4359 RegVT == MVT::v4bf16)
4360 RC = &ARM::DPRRegClass;
4361 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4362 RegVT == MVT::v8bf16)
4363 RC = &ARM::QPRRegClass;
4364 else if (RegVT == MVT::i32)
4366 : &ARM::GPRRegClass;
4412 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4418 if (index != lastInsIndex)
4420 ISD::ArgFlagsTy
Flags =
Ins[index].Flags;
4426 if (
Flags.isByVal()) {
4427 assert(Ins[index].isOrigArg() &&
4428 "Byval arguments cannot be implicit");
4432 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4466 lastInsIndex = index;
4473 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4474 TotalArgRegsSaveSize);
4478 "secure entry function must not be variadic", dl.
getDebugLoc()));
4488 assert(StackAlign &&
"data layout string is missing stack alignment");
4489 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4498 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4507 return CFP->getValueAPF().isPosZero();
4510 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4511 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4514 return CFP->getValueAPF().isPosZero();
4516 }
else if (
Op->getOpcode() == ISD::BITCAST &&
4517 Op->getValueType(0) == MVT::f64) {
4521 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4532 const SDLoc &dl)
const {
4534 unsigned C = RHSC->getZExtValue();
4598 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4602 unsigned Mask =
LHS.getConstantOperandVal(1);
4604 uint64_t RHSV = RHSC->getZExtValue();
4605 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4607 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4621 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4624 LHS.getConstantOperandVal(1) < 31) {
4625 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4650 unsigned CompareType;
4653 CompareType = ARMISD::CMP;
4658 CompareType = ARMISD::CMPZ;
4668 bool Signaling)
const {
4669 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4675 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4684std::pair<SDValue, SDValue>
4687 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4699 switch (
Op.getOpcode()) {
4751 return std::make_pair(
Value, OverflowCmp);
4762 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4767 EVT VT =
Op.getValueType();
4770 DAG.
getNode(ARMISD::CMOV, dl, VT, TVal, FVal, ARMcc, OverflowCmp);
4772 SDVTList VTs = DAG.
getVTList(
Op.getValueType(), MVT::i32);
4810 EVT VT =
Op.getValueType();
4811 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4814 switch (
Op.getOpcode()) {
4839 EVT VT =
Op.getValueType();
4840 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4850 switch (
Op->getOpcode()) {
4852 NewOpcode = ARMISD::UQADD8b;
4855 NewOpcode = ARMISD::QADD8b;
4858 NewOpcode = ARMISD::UQSUB8b;
4861 NewOpcode = ARMISD::QSUB8b;
4866 switch (
Op->getOpcode()) {
4868 NewOpcode = ARMISD::UQADD16b;
4871 NewOpcode = ARMISD::QADD16b;
4874 NewOpcode = ARMISD::UQSUB16b;
4877 NewOpcode = ARMISD::QSUB16b;
4885 DAG.
getNode(NewOpcode, dl, MVT::i32,
4896 unsigned Opc =
Cond.getOpcode();
4898 if (
Cond.getResNo() == 1 &&
4906 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4907 EVT VT =
Op.getValueType();
4909 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4917 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4918 const ConstantSDNode *CMOVTrue =
4920 const ConstantSDNode *CMOVFalse =
4923 if (CMOVTrue && CMOVFalse) {
4929 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
4931 False = SelectFalse;
4932 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
4938 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
4939 Cond.getOperand(3), DAG);
4954 bool &swpCmpOps,
bool &swpVselOps) {
4982 swpCmpOps = !swpCmpOps;
4983 swpVselOps = !swpVselOps;
5006 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5008 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5010 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5024 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5045 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5047 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5068 EVT VT =
Op.getValueType();
5090 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5103 int64_t PosVal = std::max(Val1, Val2);
5104 int64_t NegVal = std::min(Val1, Val2);
5116 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5119 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5151 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5156 if (*K != KTmp || V != VTmp)
5167bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5169 return !Subtarget->hasVFP2Base();
5171 return !Subtarget->hasFP64();
5173 return !Subtarget->hasFullFP16();
5178 EVT VT =
Op.getValueType();
5182 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5194 if (VT == MVT::i32 &&
5214 if (
Op.getValueType().isInteger()) {
5222 LHS.getValueType() ==
RHS.getValueType()) {
5223 EVT VT =
LHS.getValueType();
5229 Shift = DAG.
getNOT(dl, Shift, VT);
5235 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5236 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5239 unsigned Opcode = 0;
5241 if (TVal == ~FVal) {
5242 Opcode = ARMISD::CSINV;
5243 }
else if (TVal == ~FVal + 1) {
5244 Opcode = ARMISD::CSNEG;
5245 }
else if (TVal + 1 == FVal) {
5246 Opcode = ARMISD::CSINC;
5247 }
else if (TVal == FVal + 1) {
5248 Opcode = ARMISD::CSINC;
5257 if (Opcode != ARMISD::CSINC &&
5267 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5278 EVT VT =
TrueVal.getValueType();
5279 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5283 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5288 if (!
RHS.getNode()) {
5294 if (
LHS.getValueType() == MVT::i32) {
5305 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5306 TrueVal.getValueType() == MVT::f32 ||
5307 TrueVal.getValueType() == MVT::f64)) {
5321 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5331 if (Subtarget->hasFPARMv8Base() &&
5333 (
TrueVal.getValueType() == MVT::f16 ||
5334 TrueVal.getValueType() == MVT::f32 ||
5335 TrueVal.getValueType() == MVT::f64)) {
5336 bool swpCmpOps =
false;
5337 bool swpVselOps =
false;
5351 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5354 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5364 if (!
N->hasOneUse())
5367 if (!
N->getNumValues())
5369 EVT VT =
Op.getValueType();
5370 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5387 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5388 Ld->getPointerInfo(), Ld->getAlign(),
5389 Ld->getMemOperand()->getFlags());
5405 SDValue Ptr = Ld->getBasePtr();
5407 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5408 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5413 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5414 Ld->getPointerInfo().getWithOffset(4),
5416 Ld->getMemOperand()->getFlags());
5434 bool LHSSeenZero =
false;
5436 bool RHSSeenZero =
false;
5438 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5449 if (
LHS.getValueType() == MVT::f32) {
5455 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5467 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5468 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5483 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5495 unsigned Opc =
Cond.getOpcode();
5497 !Subtarget->isThumb1Only();
5498 if (
Cond.getResNo() == 1 &&
5508 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5514 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5516 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5531 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5536 if (!
RHS.getNode()) {
5544 unsigned Opc =
LHS.getOpcode();
5546 !Subtarget->isThumb1Only();
5558 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5565 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5568 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5572 if (
LHS.getValueType() == MVT::i32) {
5575 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5578 SDNodeFlags
Flags =
Op->getFlags();
5579 if (
Flags.hasNoNaNs() &&
5584 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5598 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5612 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5615 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5620 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5621 Addr,
Op.getOperand(2), JTI);
5625 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5629 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5632 DAG.
getLoad(PTy, dl, Chain, Addr,
5635 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5640 EVT VT =
Op.getValueType();
5643 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5644 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5652 const EVT OpTy =
Op.getOperand(0).getValueType();
5653 if (OpTy == MVT::v4f32)
5655 else if (OpTy == MVT::v4f16 && HasFullFP16)
5657 else if (OpTy == MVT::v8f16 && HasFullFP16)
5662 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5665 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5670 EVT VT =
Op.getValueType();
5674 bool IsStrict =
Op->isStrictFPOpcode();
5675 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5677 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5690 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5691 CallOptions, Loc, Chain);
5701 Loc,
Op.getValueType(), SrcVal);
5710 EVT VT =
Op.getValueType();
5712 EVT FromVT =
Op.getOperand(0).getValueType();
5714 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5716 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5717 Subtarget->hasFP64())
5719 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5720 Subtarget->hasFullFP16())
5722 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5723 Subtarget->hasMVEFloatOps())
5725 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5726 Subtarget->hasMVEFloatOps())
5729 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5746 EVT VT =
Op.getValueType();
5749 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5755 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5756 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5757 "Invalid type for custom lowering!");
5762 if (VT == MVT::v4f32)
5763 DestVecType = MVT::v4i32;
5764 else if (VT == MVT::v4f16 && HasFullFP16)
5765 DestVecType = MVT::v4i16;
5766 else if (VT == MVT::v8f16 && HasFullFP16)
5767 DestVecType = MVT::v8i16;
5773 switch (
Op.getOpcode()) {
5785 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5790 EVT VT =
Op.getValueType();
5793 if (isUnsupportedFloatingType(VT)) {
5803 CallOptions, SDLoc(
Op)).first;
5814 EVT VT =
Op.getValueType();
5816 bool InGPR = Tmp0.
getOpcode() == ISD::BITCAST ||
5818 bool UseNEON = !InGPR && Subtarget->hasNEON();
5825 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5828 DAG.
getNode(ISD::BITCAST, dl, OpVT, Mask),
5832 if (SrcVT == MVT::f32) {
5835 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5836 DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1),
5838 }
else if (VT == MVT::f32)
5839 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5840 DAG.
getNode(ISD::BITCAST, dl, MVT::v1i64, Tmp1),
5842 Tmp0 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp0);
5843 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1);
5854 if (VT == MVT::f32) {
5855 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::v2f32, Res);
5859 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Res);
5866 if (SrcVT == MVT::f64)
5869 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp1);
5875 if (VT == MVT::f32) {
5877 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
5878 return DAG.
getNode(ISD::BITCAST, dl, MVT::f32,
5888 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5896 EVT VT =
Op.getValueType();
5898 unsigned Depth =
Op.getConstantOperandVal(0);
5900 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5904 MachinePointerInfo());
5913 const ARMBaseRegisterInfo &ARI =
5914 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
5919 EVT VT =
Op.getValueType();
5921 unsigned Depth =
Op.getConstantOperandVal(0);
5926 MachinePointerInfo());
5934 return StringSwitch<Register>(
RegName)
5935 .Case(
"sp", ARM::SP)
5946 assert(
N->getValueType(0) == MVT::i64
5947 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
5950 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
5990 const APInt &APIntIndex = Index->getAPIntValue();
5992 NewIndex *= APIntIndex;
6004 SDValue BitCast = DAG.
getNode(ISD::BITCAST, dl, VecVT, ExtractSrc);
6021 EVT SrcVT =
Op.getValueType();
6022 EVT DstVT =
N->getValueType(0);
6024 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6025 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6026 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6029 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6030 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6031 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6038 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6049 return DAG.
getNode(ISD::BITCAST, dl, DstVT,
6050 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6058 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6060 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6062 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6082 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6083 return DAG.
getNode(ISD::BITCAST, dl, VT, Vmov);
6091 EVT VT =
Op.getValueType();
6113 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6123 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6134 EVT VT =
Op.getValueType();
6155 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6176 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6228 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6256 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6286 EVT VT =
N->getValueType(0);
6287 if (VT.
isVector() && ST->hasNEON()) {
6296 if (ElemTy == MVT::i8) {
6304 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6307 unsigned NumBits = ElemTy.getSizeInBits();
6309 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6319 if (ElemTy == MVT::i64) {
6332 if (!ST->hasV6T2Ops())
6341 EVT VT =
N->getValueType(0);
6344 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6345 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6346 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6347 "Unexpected type for custom ctpop lowering");
6355 unsigned EltSize = 8;
6377 while (
Op.getOpcode() == ISD::BITCAST)
6378 Op =
Op.getOperand(0);
6380 APInt SplatBits, SplatUndef;
6381 unsigned SplatBitSize;
6384 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6386 SplatBitSize > ElementBits)
6397 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6401 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6412 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6417 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6418 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6427 EVT VT =
N->getValueType(0);
6442 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6444 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6449 "unexpected vector shift opcode");
6451 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6452 unsigned VShiftOpc =
6453 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6454 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6460 EVT ShiftVT =
N->getOperand(1).getValueType();
6463 unsigned VShiftOpc =
6464 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6465 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6470 EVT VT =
N->getValueType(0);
6479 "Unknown shift to lower!");
6481 unsigned ShOpc =
N->getOpcode();
6482 if (ST->hasMVEIntegerOps()) {
6484 unsigned ShPartsOpc = ARMISD::LSLL;
6505 ShPartsOpc = ARMISD::LSRL;
6507 ShPartsOpc = ARMISD::ASRL;
6512 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6526 if (ST->isThumb1Only())
6531 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6535 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6539 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6547 bool Invert =
false;
6554 EVT VT =
Op.getValueType();
6562 assert(ST->hasMVEIntegerOps() &&
6563 "No hardware support for integer vector comparison!");
6565 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6586 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6588 Merged = DAG.
getNode(ISD::BITCAST, dl, CmpVT, Merged);
6590 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6600 switch (SetCCOpcode) {
6604 if (ST->hasMVEFloatOps()) {
6607 Invert =
true; [[fallthrough]];
6612 case ISD::SETLT: Swap =
true; [[fallthrough]];
6616 case ISD::SETLE: Swap =
true; [[fallthrough]];
6632 Result = DAG.
getNOT(dl, Result, VT);
6635 case ISD::SETUO: Invert =
true; [[fallthrough]];
6644 Result = DAG.
getNOT(dl, Result, VT);
6650 switch (SetCCOpcode) {
6653 if (ST->hasMVEIntegerOps()) {
6656 Invert =
true; [[fallthrough]];
6659 case ISD::SETLT: Swap =
true; [[fallthrough]];
6661 case ISD::SETLE: Swap =
true; [[fallthrough]];
6678 if (AndOp.getNode() && AndOp.getOpcode() == ISD::BITCAST)
6681 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6682 Op0 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(0));
6683 Op1 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(1));
6686 Result = DAG.
getNOT(dl, Result, VT);
6711 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6714 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6720 Result = DAG.
getNOT(dl, Result, VT);
6732 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6748 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6759 unsigned OpCmode, Imm;
6770 switch (SplatBitSize) {
6775 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6778 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6783 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6784 if ((SplatBits & ~0xff) == 0) {
6790 if ((SplatBits & ~0xff00) == 0) {
6793 Imm = SplatBits >> 8;
6803 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6804 if ((SplatBits & ~0xff) == 0) {
6810 if ((SplatBits & ~0xff00) == 0) {
6813 Imm = SplatBits >> 8;
6816 if ((SplatBits & ~0xff0000) == 0) {
6819 Imm = SplatBits >> 16;
6822 if ((SplatBits & ~0xff000000) == 0) {
6825 Imm = SplatBits >> 24;
6832 if ((SplatBits & ~0xffff) == 0 &&
6833 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6836 Imm = SplatBits >> 8;
6844 if ((SplatBits & ~0xffffff) == 0 &&
6845 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6848 Imm = SplatBits >> 16;
6864 unsigned ImmMask = 1;
6866 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6867 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6869 }
else if ((SplatBits & BitMask) != 0) {
6878 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6892 EVT VT =
Op.getValueType();
6893 bool IsDouble = (VT == MVT::f64);
6899 if (
ST->genExecuteOnly()) {
6901 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6902 "Unexpected architecture");
6920 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
6925 if (!
ST->hasVFP3Base())
6930 if (IsDouble && !Subtarget->hasFP64())
6937 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
6955 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
6964 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
6975 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
6992 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
7018 unsigned ExpectedElt = Imm;
7019 for (
unsigned i = 1; i < NumElts; ++i) {
7023 if (ExpectedElt == NumElts)
7026 if (M[i] < 0)
continue;
7027 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7035 bool &ReverseVEXT,
unsigned &Imm) {
7037 ReverseVEXT =
false;
7048 unsigned ExpectedElt = Imm;
7049 for (
unsigned i = 1; i < NumElts; ++i) {
7053 if (ExpectedElt == NumElts * 2) {
7058 if (M[i] < 0)
continue;
7059 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7074 return VT == MVT::v8i8 && M.size() == 8;
7079 if (Mask.size() == Elements * 2)
7080 return Index / Elements;
7081 return Mask[Index] == 0 ? 0 : 1;
7111 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7119 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7121 for (
unsigned j = 0; j < NumElts; j += 2) {
7122 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7123 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7128 if (M.size() == NumElts*2)
7143 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7146 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7148 for (
unsigned j = 0; j < NumElts; j += 2) {
7149 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7150 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7155 if (M.size() == NumElts*2)
7175 if (M.size() != NumElts && M.size() != NumElts*2)
7178 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7180 for (
unsigned j = 0; j < NumElts; ++j) {
7181 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7186 if (M.size() == NumElts*2)
7205 if (M.size() != NumElts && M.size() != NumElts*2)
7208 unsigned Half = NumElts / 2;
7209 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7211 for (
unsigned j = 0; j < NumElts; j += Half) {
7212 unsigned Idx = WhichResult;
7213 for (
unsigned k = 0; k < Half; ++k) {
7214 int MIdx = M[i + j + k];
7215 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7222 if (M.size() == NumElts*2)
7246 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7249 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7251 unsigned Idx = WhichResult * NumElts / 2;
7252 for (
unsigned j = 0; j < NumElts; j += 2) {
7253 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7254 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7260 if (M.size() == NumElts*2)
7279 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7282 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7284 unsigned Idx = WhichResult * NumElts / 2;
7285 for (
unsigned j = 0; j < NumElts; j += 2) {
7286 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7287 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7293 if (M.size() == NumElts*2)
7306 unsigned &WhichResult,
7309 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7310 return ARMISD::VTRN;
7311 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7312 return ARMISD::VUZP;
7313 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7314 return ARMISD::VZIP;
7318 return ARMISD::VTRN;
7320 return ARMISD::VUZP;
7322 return ARMISD::VZIP;
7331 if (NumElts != M.size())
7335 for (
unsigned i = 0; i != NumElts; ++i)
7336 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7345 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7353 int Ofs = Top ? 1 : 0;
7354 int Upper = SingleSource ? 0 : NumElts;
7355 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7356 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7358 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7367 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7376 unsigned Offset = Top ? 0 : 1;
7377 unsigned N = SingleSource ? 0 : NumElts;
7378 for (
unsigned i = 0; i < NumElts; i += 2) {
7379 if (M[i] >= 0 && M[i] != (
int)i)
7381 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7390 if (NumElts != M.size())
7398 unsigned Off0 = rev ? NumElts / 2 : 0;
7399 unsigned Off1 = rev ? 0 : NumElts / 2;
7400 for (
unsigned i = 0; i < NumElts; i += 2) {
7401 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7403 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7419 if (!ST->hasMVEFloatOps())
7424 if (VT != MVT::v8f16)
7445 for (
unsigned i = 1; i < 4; i++) {
7460 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7472 if (!ST->hasMVEFloatOps())
7477 if (VT != MVT::v4f32)
7493 for (
unsigned i = 1; i < 4; i++) {
7495 return Trunc.
getOpcode() == ISD::FP_EXTEND &&
7504 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7516 Val =
N->getAsZExtVal();
7518 if (ST->isThumb1Only()) {
7519 if (Val <= 255 || ~Val <= 255)
7531 EVT VT =
Op.getValueType();
7533 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7537 unsigned BitsPerBool;
7541 }
else if (NumElts == 4) {
7544 }
else if (NumElts == 8) {
7547 }
else if (NumElts == 16) {
7558 return U.get().isUndef() || U.get() == FirstOp;
7562 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7566 unsigned Bits32 = 0;
7567 for (
unsigned i = 0; i < NumElts; ++i) {
7571 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7573 Bits32 |= BoolMask << (i * BitsPerBool);
7579 for (
unsigned i = 0; i < NumElts; ++i) {
7592 if (!ST->hasMVEIntegerOps())
7596 EVT VT =
Op.getValueType();
7606 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7610 for (
unsigned I = 2;
I < NumElts;
I++) {
7626 switch (
N->getOpcode()) {
7637 return N->getOperand(1).getNode() ==
Op;
7639 switch (
N->getConstantOperandVal(0)) {
7640 case Intrinsic::arm_mve_add_predicated:
7641 case Intrinsic::arm_mve_mul_predicated:
7642 case Intrinsic::arm_mve_qadd_predicated:
7643 case Intrinsic::arm_mve_vhadd:
7644 case Intrinsic::arm_mve_hadd_predicated:
7645 case Intrinsic::arm_mve_vqdmulh:
7646 case Intrinsic::arm_mve_qdmulh_predicated:
7647 case Intrinsic::arm_mve_vqrdmulh:
7648 case Intrinsic::arm_mve_qrdmulh_predicated:
7649 case Intrinsic::arm_mve_vqdmull:
7650 case Intrinsic::arm_mve_vqdmull_predicated:
7652 case Intrinsic::arm_mve_sub_predicated:
7653 case Intrinsic::arm_mve_qsub_predicated:
7654 case Intrinsic::arm_mve_vhsub:
7655 case Intrinsic::arm_mve_hsub_predicated:
7656 return N->getOperand(2).getNode() ==
Op;
7671 EVT VT =
Op.getValueType();
7679 APInt SplatBits, SplatUndef;
7680 unsigned SplatBitSize;
7682 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7689 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7691 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7692 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7693 : SplatBitSize == 16 ? MVT::v8i16
7697 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7700 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7701 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7706 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7710 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7714 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7716 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7720 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7724 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7728 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7734 if (
ST->hasMVEIntegerOps() &&
7735 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7736 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7737 : SplatBitSize == 16 ? MVT::v8i16
7741 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7754 bool isOnlyLowElement =
true;
7755 bool usesOnlyOneValue =
true;
7756 bool hasDominantValue =
false;
7761 DenseMap<SDValue, unsigned> ValueCounts;
7763 for (
unsigned i = 0; i < NumElts; ++i) {
7768 isOnlyLowElement =
false;
7772 unsigned &
Count = ValueCounts[
V];
7775 if (++
Count > (NumElts / 2)) {
7776 hasDominantValue =
true;
7780 if (ValueCounts.
size() != 1)
7781 usesOnlyOneValue =
false;
7782 if (!
Value.getNode() && !ValueCounts.
empty())
7785 if (ValueCounts.
empty())
7797 if (hasDominantValue && EltSize <= 32) {
7806 ConstantSDNode *constIndex;
7813 if (VT !=
Value->getOperand(0).getValueType()) {
7816 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7821 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7826 if (!usesOnlyOneValue) {
7829 for (
unsigned I = 0;
I < NumElts; ++
I) {
7834 Ops.push_back(
Op.getOperand(
I));
7844 assert(FVT == MVT::f32 || FVT == MVT::f16);
7845 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7846 for (
unsigned i = 0; i < NumElts; ++i)
7847 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, IVT,
7851 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7853 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
7855 if (usesOnlyOneValue) {
7858 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7882 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7902 if (EltSize >= 32) {
7908 for (
unsigned i = 0; i < NumElts; ++i)
7909 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, EltVT,
Op.getOperand(i)));
7911 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
7922 for (
unsigned i = 0 ; i < NumElts; ++i) {
7941 EVT VT =
Op.getValueType();
7944 struct ShuffleSourceInfo {
7946 unsigned MinElt = std::numeric_limits<unsigned>::max();
7947 unsigned MaxElt = 0;
7957 int WindowScale = 1;
7959 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7967 for (
unsigned i = 0; i < NumElts; ++i) {
7982 SDValue SourceVec =
V.getOperand(0);
7984 if (Source == Sources.
end())
7988 unsigned EltNo =
V.getConstantOperandVal(1);
7995 if (Sources.
size() > 2)
8001 for (
auto &Source : Sources) {
8002 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8003 if (SrcEltTy.
bitsLT(SmallestEltTy))
8004 SmallestEltTy = SrcEltTy;
8006 unsigned ResMultiplier =
8014 for (
auto &Src : Sources) {
8015 EVT SrcVT = Src.ShuffleVec.getValueType();
8019 if (SrcVTSize == VTSize)
8028 if (SrcVTSize < VTSize) {
8029 if (2 * SrcVTSize != VTSize)
8035 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8039 if (SrcVTSize != 2 * VTSize)
8042 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8047 if (Src.MinElt >= NumSrcElts) {
8052 Src.WindowBase = -NumSrcElts;
8053 }
else if (Src.MaxElt < NumSrcElts) {
8067 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8070 Src.WindowBase = -Src.MinElt;
8077 for (
auto &Src : Sources) {
8078 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8079 if (SrcEltTy == SmallestEltTy)
8082 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8084 Src.WindowBase *= Src.WindowScale;
8089 for (
auto Src : Sources)
8090 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8098 if (
Entry.isUndef())
8107 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8110 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8114 int *LaneMask = &
Mask[i * ResMultiplier];
8116 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8117 ExtractBase += NumElts * (Src - Sources.begin());
8118 for (
int j = 0;
j < LanesDefined; ++
j)
8119 LaneMask[j] = ExtractBase + j;
8125 assert(Sources.size() <= 2 &&
"Too many sources!");
8128 for (
unsigned i = 0; i < Sources.size(); ++i)
8135 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8157 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8177 unsigned PFIndexes[4];
8178 for (
unsigned i = 0; i != 4; ++i) {
8182 PFIndexes[i] = M[i];
8186 unsigned PFTableIndex =
8187 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8189 unsigned Cost = (PFEntry >> 30);
8195 bool ReverseVEXT, isV_UNDEF;
8196 unsigned Imm, WhichResult;
8199 if (EltSize >= 32 ||
8206 else if (Subtarget->hasNEON() &&
8211 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8214 else if (Subtarget->hasMVEIntegerOps() &&
8218 else if (Subtarget->hasMVEIntegerOps() &&
8232 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8233 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8234 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8237 if (LHSID == (1*9+2)*9+3)
return LHS;
8238 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8252 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8255 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8258 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8263 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8268 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8295 for (
int I : ShuffleMask)
8299 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8, V1,
8302 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8, V1, V2,
8308 EVT VT =
Op.getValueType();
8310 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8311 "Expect an v8i16/v16i8 type");
8317 std::vector<int> NewMask;
8321 NewMask.push_back(i);
8351 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8361 if (VT != MVT::v16i1)
8362 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8372 return DAG.
getNode(ISD::BITCAST, dl, NewVT, PredAsVector);
8377 EVT VT =
Op.getValueType();
8381 assert(ST->hasMVEIntegerOps() &&
8382 "No support for vector shuffle of boolean predicates");
8392 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8408 "Expected identical vector type in expanded i1 shuffle!");
8412 PredAsVector2, ShuffleMask);
8417 if (VT == MVT::v2i1) {
8418 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8421 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8423 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8434 EVT VT =
Op.getValueType();
8438 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8439 "Unexpected vector type");
8441 int QuarterSize = NumElts / 4;
8450 for (
int i = 0; i <
Length; i++) {
8451 if (ShuffleMask[Start + i] >= 0) {
8452 if (ShuffleMask[Start + i] %
Length != i)
8454 MovIdx = ShuffleMask[Start + i] /
Length;
8462 for (
int i = 1; i <
Length; i++) {
8463 if (ShuffleMask[Start + i] >= 0 &&
8464 (ShuffleMask[Start + i] /
Length != MovIdx ||
8465 ShuffleMask[Start + i] %
Length != i))
8471 for (
int Part = 0; Part < 4; ++Part) {
8473 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8487 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8492 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8494 for (
int Part = 0; Part < 4; ++Part)
8495 for (
int i = 0; i < QuarterSize; i++)
8497 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8499 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8502 for (
int Part = 0; Part < 4; ++Part)
8518 EVT VT =
Op.getValueType();
8530 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8534 if (Mask[i] != i + BaseOffset) {
8535 if (OffElement == -1)
8541 return NonUndef > 2 && OffElement != -1;
8545 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8547 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8558 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8569 EVT VT =
Op.getValueType();
8573 if (ST->hasMVEIntegerOps() && EltSize == 1)
8584 if (EltSize <= 32) {
8588 if (Lane == -1) Lane = 0;
8599 bool IsScalarToVector =
true;
8602 IsScalarToVector =
false;
8605 if (IsScalarToVector)
8608 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT, V1,
8612 bool ReverseVEXT =
false;
8614 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8617 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V2,
8622 return DAG.
getNode(ARMISD::VREV64, dl, VT, V1);
8624 return DAG.
getNode(ARMISD::VREV32, dl, VT, V1);
8626 return DAG.
getNode(ARMISD::VREV16, dl, VT, V1);
8629 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V1,
8638 unsigned WhichResult = 0;
8639 bool isV_UNDEF =
false;
8640 if (ST->hasNEON()) {
8642 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8649 if (ST->hasMVEIntegerOps()) {
8651 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2, V1,
8654 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V2,
8657 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V1,
8684 }) &&
"Unexpected shuffle index into UNDEF operand!");
8687 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8690 assert((WhichResult == 0) &&
8691 "In-place shuffle of concat can only have one result!");
8700 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8704 for (
bool Top : {
false,
true}) {
8705 for (
bool SingleSource : {
false,
true}) {
8706 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8711 SingleSource ? V1 : V2);
8727 unsigned PFIndexes[4];
8728 for (
unsigned i = 0; i != 4; ++i) {
8729 if (ShuffleMask[i] < 0)
8732 PFIndexes[i] = ShuffleMask[i];
8736 unsigned PFTableIndex =
8737 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8739 unsigned Cost = (PFEntry >> 30);
8745 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8746 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8756 if (EltSize >= 32) {
8761 V1 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V1);
8762 V2 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V2);
8764 for (
unsigned i = 0; i < NumElts; ++i) {
8765 if (ShuffleMask[i] < 0)
8769 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8774 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8777 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8781 if (ST->hasNEON() && VT == MVT::v8i8)
8785 if (ST->hasMVEIntegerOps())
8794 EVT VecVT =
Op.getOperand(0).getValueType();
8797 assert(ST->hasMVEIntegerOps() &&
8798 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8801 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8802 unsigned Lane =
Op.getConstantOperandVal(2);
8803 unsigned LaneWidth =
8805 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8810 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8823 if (Subtarget->hasMVEIntegerOps() &&
8824 Op.getValueType().getScalarSizeInBits() == 1)
8848 IVecIn, IElt, Lane);
8849 return DAG.
getNode(ISD::BITCAST, dl, VecVT, IVecOut);
8857 EVT VecVT =
Op.getOperand(0).getValueType();
8860 assert(ST->hasMVEIntegerOps() &&
8861 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8864 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8865 unsigned Lane =
Op.getConstantOperandVal(1);
8866 unsigned LaneWidth =
8888 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8897 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8898 "Unexpected custom CONCAT_VECTORS lowering");
8900 "Unexpected custom CONCAT_VECTORS lowering");
8901 assert(ST->hasMVEIntegerOps() &&
8902 "CONCAT_VECTORS lowering only supported for MVE");
8906 EVT Op2VT = V2.getValueType();
8907 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8908 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8909 "Unexpected i1 concat operations!");
8922 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8927 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8936 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8937 EVT NewVT = NewV.getValueType();
8938 EVT ConcatVT = ConVec.getValueType();
8939 unsigned ExtScale = 1;
8940 if (NewVT == MVT::v2f64) {
8941 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8954 ConVec = ExtractInto(NewV1, ConVec, j);
8955 ConVec = ExtractInto(NewV2, ConVec, j);
8959 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8965 while (ConcatOps.
size() > 1) {
8966 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8969 ConcatOps[
I / 2] = ConcatPair(V1, V2);
8973 return ConcatOps[0];
8978 EVT VT =
Op->getValueType(0);
8984 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
8985 "unexpected CONCAT_VECTORS");
8992 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op0),
8996 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op1),
8998 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Val);
9006 EVT VT =
Op.getValueType();
9012 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9013 assert(ST->hasMVEIntegerOps() &&
9014 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9024 EVT SubVT = MVT::v4i32;
9026 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9036 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
9041 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9050 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9057 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9058 EVT VT =
N->getValueType(0);
9059 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9060 "Expected a vector i1 type!");
9062 EVT FromVT =
Op.getValueType();
9073 if (!Subtarget->hasMVEIntegerOps())
9076 EVT ToVT =
N->getValueType(0);
9119 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9121 EVT FromVT =
N->getOperand(0).getValueType();
9122 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9133 if (!Subtarget->hasMVEIntegerOps())
9138 EVT ToVT =
N->getValueType(0);
9139 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9142 EVT FromVT =
Op.getValueType();
9143 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9154 SDValue Ext1 = Ext.getValue(1);
9157 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9158 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9170 EVT VT =
N->getValueType(0);
9171 if (VT == MVT::v2i64 &&
N->getOpcode() == ISD::BITCAST) {
9172 SDNode *BVN =
N->getOperand(0).getNode();
9177 unsigned HiElt = 1 - LoElt;
9182 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9198 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9199 SDNode *Elt =
N->getOperand(i).getNode();
9202 unsigned HalfSize = EltSize / 2;
9204 if (!
isIntN(HalfSize,
C->getSExtValue()))
9207 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9246 switch (OrigSimpleTy) {
9262 unsigned ExtOpcode) {
9285 if (ExtendedTy == LD->getMemoryVT())
9286 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9287 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9288 LD->getMemOperand()->getFlags());
9294 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9295 LD->getMemoryVT(), LD->getAlign(),
9296 LD->getMemOperand()->getFlags());
9309 N->getOperand(0)->getValueType(0),
9315 "Expected extending load");
9321 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9329 if (
N->getOpcode() == ISD::BITCAST) {
9330 SDNode *BVN =
N->getOperand(0).getNode();
9332 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9340 EVT VT =
N->getValueType(0);
9346 for (
unsigned i = 0; i != NumElts; ++i) {
9347 const APInt &CInt =
N->getConstantOperandAPInt(i);
9356 unsigned Opcode =
N->getOpcode();
9358 SDNode *N0 =
N->getOperand(0).getNode();
9359 SDNode *N1 =
N->getOperand(1).getNode();
9367 unsigned Opcode =
N->getOpcode();
9369 SDNode *N0 =
N->getOperand(0).getNode();
9370 SDNode *N1 =
N->getOperand(1).getNode();
9380 EVT VT =
Op.getValueType();
9382 "unexpected type for custom-lowering ISD::MUL");
9383 SDNode *N0 =
Op.getOperand(0).getNode();
9384 SDNode *N1 =
Op.getOperand(1).getNode();
9385 unsigned NewOpc = 0;
9389 if (isN0SExt && isN1SExt)
9390 NewOpc = ARMISD::VMULLs;
9394 if (isN0ZExt && isN1ZExt)
9395 NewOpc = ARMISD::VMULLu;
9396 else if (isN1SExt || isN1ZExt) {
9400 NewOpc = ARMISD::VMULLs;
9403 NewOpc = ARMISD::VMULLu;
9407 NewOpc = ARMISD::VMULLu;
9413 if (VT == MVT::v2i64)
9430 "unexpected types for extended operands to VMULL");
9431 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9447 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N00), Op1),
9449 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N01), Op1));
9466 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9473 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32,
X);
9476 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32,
X);
9500 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9503 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9511 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9514 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9524 EVT VT =
Op.getValueType();
9525 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9526 "unexpected type for custom-lowering ISD::SDIV");
9533 if (VT == MVT::v8i8) {
9561 EVT VT =
Op.getValueType();
9562 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9563 "unexpected type for custom-lowering ISD::UDIV");
9570 if (VT == MVT::v8i8) {
9609 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9612 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9616 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9624 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9627 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9637 EVT VT =
N->getValueType(0);
9650 Result = DAG.
getNode(ARMISD::ADDE,
DL, VTs,
Op.getOperand(0),
9651 Op.getOperand(1), Carry);
9664 Result = DAG.
getNode(ARMISD::SUBE,
DL, VTs,
Op.getOperand(0),
9665 Op.getOperand(1), Carry);
9682 EVT VT =
Op.getValueType();
9683 assert((VT == MVT::i32 || VT == MVT::i64) &&
9684 "unexpected type for custom lowering DIV");
9690 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9692 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9699 for (
auto AI : {1, 0}) {
9701 Args.emplace_back(Operand,
9709 ES, std::move(Args));
9719ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9727 const bool MinSize =
ST.hasMinSize();
9728 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9729 :
ST.hasDivideInARMMode();
9733 if (
N->getOperand(0).getValueType().isVector())
9738 if (!(MinSize && HasDivide))
9751 if (Divisor.
sgt(128))
9759 assert(
Op.getValueType() == MVT::i32 &&
9760 "unexpected type for custom lowering DIV");
9763 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9766 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9772 if (
N->getValueType(0) == MVT::i32)
9773 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9776 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9780void ARMTargetLowering::ExpandDIV_Windows(
9785 assert(
Op.getValueType() == MVT::i64 &&
9786 "unexpected type for custom lowering DIV");
9803 EVT MemVT = LD->getMemoryVT();
9804 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9805 MemVT == MVT::v16i1) &&
9806 "Expected a predicate type!");
9807 assert(MemVT ==
Op.getValueType());
9809 "Expected a non-extending load");
9810 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9824 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9826 LD->getMemOperand());
9832 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9833 if (MemVT != MVT::v16i1)
9842 EVT MemVT =
LD->getMemoryVT();
9843 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9845 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9846 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9847 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9850 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9851 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9861 EVT MemVT = ST->getMemoryVT();
9862 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9863 MemVT == MVT::v16i1) &&
9864 "Expected a predicate type!");
9865 assert(MemVT == ST->getValue().getValueType());
9866 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9867 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9872 SDValue Build = ST->getValue();
9873 if (MemVT != MVT::v16i1) {
9886 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9892 ST->getChain(), dl, GRP, ST->getBasePtr(),
9894 ST->getMemOperand());
9900 EVT MemVT = ST->getMemoryVT();
9901 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
9903 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9919 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
9920 MemVT, ST->getMemOperand());
9921 }
else if (Subtarget->hasMVEIntegerOps() &&
9922 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9923 MemVT == MVT::v16i1))) {
9932 (
N->getOpcode() == ARMISD::VMOVIMM &&
9938 MVT VT =
Op.getSimpleValueType();
9940 SDValue PassThru =
N->getPassThru();
9951 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
9952 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
9953 N->getExtensionType(),
N->isExpandingLoad());
9955 bool PassThruIsCastZero = (PassThru.
getOpcode() == ISD::BITCAST ||
9956 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
9958 if (!PassThru.
isUndef() && !PassThruIsCastZero)
9965 if (!ST->hasMVEIntegerOps())
9969 unsigned BaseOpcode = 0;
9970 switch (
Op->getOpcode()) {
9972 case ISD::VECREDUCE_FADD: BaseOpcode =
ISD::FADD;
break;
9973 case ISD::VECREDUCE_FMUL: BaseOpcode =
ISD::FMUL;
break;
9974 case ISD::VECREDUCE_MUL: BaseOpcode =
ISD::MUL;
break;
9975 case ISD::VECREDUCE_AND: BaseOpcode =
ISD::AND;
break;
9976 case ISD::VECREDUCE_OR: BaseOpcode =
ISD::OR;
break;
9977 case ISD::VECREDUCE_XOR: BaseOpcode =
ISD::XOR;
break;
9978 case ISD::VECREDUCE_FMAX: BaseOpcode = ISD::FMAXNUM;
break;
9979 case ISD::VECREDUCE_FMIN: BaseOpcode = ISD::FMINNUM;
break;
9986 unsigned NumActiveLanes = NumElts;
9988 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
9989 NumActiveLanes == 2) &&
9990 "Only expected a power 2 vector size");
9994 while (NumActiveLanes > 4) {
9995 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
9997 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
9998 NumActiveLanes /= 2;
10002 if (NumActiveLanes == 4) {
10012 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10013 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10014 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10020 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10024 if (EltVT !=
Op->getValueType(0))
10031 if (!ST->hasMVEFloatOps())
10038 if (!ST->hasNEON())
10046 unsigned PairwiseIntrinsic = 0;
10047 switch (
Op->getOpcode()) {
10050 case ISD::VECREDUCE_UMIN:
10051 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10053 case ISD::VECREDUCE_UMAX:
10054 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10056 case ISD::VECREDUCE_SMIN:
10057 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10059 case ISD::VECREDUCE_SMAX:
10060 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10066 unsigned NumActiveLanes = NumElts;
10068 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10069 NumActiveLanes == 2) &&
10070 "Only expected a power 2 vector size");
10076 VT =
Lo.getValueType();
10078 NumActiveLanes /= 2;
10082 while (NumActiveLanes > 1) {
10084 NumActiveLanes /= 2;
10091 if (EltVT !=
Op.getValueType()) {
10092 unsigned Extend = 0;
10093 switch (
Op->getOpcode()) {
10096 case ISD::VECREDUCE_UMIN:
10097 case ISD::VECREDUCE_UMAX:
10100 case ISD::VECREDUCE_SMIN:
10101 case ISD::VECREDUCE_SMAX:
10105 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10150 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10156 SDLoc dl(V.getNode());
10157 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10167 assert(
N->getValueType(0) == MVT::i64 &&
10168 "AtomicCmpSwap on types less than 64 should be legal");
10177 ARM::CMP_SWAP_64,
SDLoc(
N),
10178 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10197 EVT VT =
Op.getValueType();
10206 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10208 Chain, IsSignaling);
10209 if (!
RHS.getNode()) {
10225 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10227 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10228 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10245 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10248 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10261 if (!IsSigned && Subtarget->isThumb1Only()) {
10279 Sub1Result, Sub1Result, Flags1);
10294 if (
Op.getValueType() != MVT::i32)
10308 unsigned Opcode = ARMISD::SUBC;
10317 bool CanUseAdd =
false;
10333 Opcode = ARMISD::ADDC;
10357 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10358 GTCondValue, Flags);
10362 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10363 LTCondValue, Flags);
10365 if (
Op.getValueType() != MVT::i32)
10373 switch (
Op.getOpcode()) {
10382 case ISD::BRCOND:
return LowerBRCOND(
Op, DAG);
10383 case ISD::BR_CC:
return LowerBR_CC(
Op, DAG);
10384 case ISD::BR_JT:
return LowerBR_JT(
Op, DAG);
10405 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10409 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10410 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10430 case ISD::SET_ROUNDING:
return LowerSET_ROUNDING(
Op, DAG);
10431 case ISD::SET_FPMODE:
10432 return LowerSET_FPMODE(
Op, DAG);
10433 case ISD::RESET_FPMODE:
10434 return LowerRESET_FPMODE(
Op, DAG);
10437 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10438 return LowerDIV_Windows(
Op, DAG,
true);
10441 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10442 return LowerDIV_Windows(
Op, DAG,
false);
10449 return LowerSignedALUO(
Op, DAG);
10452 return LowerUnsignedALUO(
Op, DAG);
10464 case ISD::VECREDUCE_MUL:
10465 case ISD::VECREDUCE_AND:
10466 case ISD::VECREDUCE_OR:
10467 case ISD::VECREDUCE_XOR:
10469 case ISD::VECREDUCE_FADD:
10470 case ISD::VECREDUCE_FMUL:
10471 case ISD::VECREDUCE_FMIN:
10472 case ISD::VECREDUCE_FMAX:
10474 case ISD::VECREDUCE_UMIN:
10475 case ISD::VECREDUCE_UMAX:
10476 case ISD::VECREDUCE_SMIN:
10477 case ISD::VECREDUCE_SMAX:
10479 case ISD::ATOMIC_LOAD:
10480 case ISD::ATOMIC_STORE:
10484 case ISD::DYNAMIC_STACKALLOC:
10485 if (Subtarget->isTargetWindows())
10486 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10491 case ISD::FP_EXTEND:
return LowerFP_EXTEND(
Op, DAG);
10495 return LowerSPONENTRY(
Op, DAG);
10496 case ISD::FP_TO_BF16:
10497 return LowerFP_TO_BF16(
Op, DAG);
10498 case ARMISD::WIN__DBZCHK:
return SDValue();
10501 return LowerCMP(
Op, DAG);
10503 return LowerABS(
Op, DAG);
10508 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10509 Op.getOperand(1).getValueType() == MVT::bf16) &&
10510 "Expected custom lowering of rounding operations only for f16");
10513 {
Op.getOperand(0),
Op.getOperand(1)});
10514 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10515 {Ext.getValue(1), Ext.getValue(0)});
10522 unsigned IntNo =
N->getConstantOperandVal(0);
10524 if (IntNo == Intrinsic::arm_smlald)
10525 Opc = ARMISD::SMLALD;
10526 else if (IntNo == Intrinsic::arm_smlaldx)
10527 Opc = ARMISD::SMLALDX;
10528 else if (IntNo == Intrinsic::arm_smlsld)
10529 Opc = ARMISD::SMLSLD;
10530 else if (IntNo == Intrinsic::arm_smlsldx)
10531 Opc = ARMISD::SMLSLDX;
10537 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10541 N->getOperand(1),
N->getOperand(2),
10553 switch (
N->getOpcode()) {
10560 Res = ExpandBITCAST(
N, DAG, Subtarget);
10569 Res = LowerREM(
N, DAG);
10573 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10584 case ISD::READCYCLECOUNTER:
10589 assert(Subtarget->isTargetWindows() &&
"can only expand DIV on Windows");
10592 case ISD::ATOMIC_CMP_SWAP:
10627 "ROPI/RWPI not currently supported with SjLj");
10636 bool isThumb = Subtarget->isThumb();
10637 bool isThumb2 = Subtarget->
isThumb2();
10640 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10646 : &ARM::GPRRegClass;
10664 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10670 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10676 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10694 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10699 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10704 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10709 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10715 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10730 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10736 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10752 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10759 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10760 : &ARM::GPRnopcRegClass;
10764 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10765 unsigned MaxCSNum = 0;
10766 for (MachineBasicBlock &BB : *MF) {
10772 for (MachineInstr &
II : BB) {
10773 if (!
II.isEHLabel())
10776 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10777 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10779 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10780 for (
unsigned Idx : CallSiteIdxs) {
10781 CallSiteNumToLPad[Idx].push_back(&BB);
10782 MaxCSNum = std::max(MaxCSNum, Idx);
10789 std::vector<MachineBasicBlock*> LPadList;
10790 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10791 LPadList.reserve(CallSiteNumToLPad.
size());
10792 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10793 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10794 for (MachineBasicBlock *
MBB : MBBList) {
10795 LPadList.push_back(
MBB);
10800 assert(!LPadList.empty() &&
10801 "No landing pad destinations for the dispatch jump table!");
10804 MachineJumpTableInfo *JTI =
10811 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10814 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10816 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10819 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10823 MF->insert(MF->end(), DispatchBB);
10824 MF->insert(MF->end(), DispContBB);
10825 MF->insert(MF->end(), TrapBB);
10829 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10831 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10835 MachineInstrBuilder MIB;
10836 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10838 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10848 unsigned NumLPads = LPadList.size();
10849 if (Subtarget->isThumb2()) {
10850 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10851 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10857 if (NumLPads < 256) {
10858 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10860 .
addImm(LPadList.size())
10863 Register VReg1 =
MRI->createVirtualRegister(TRC);
10864 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10865 .
addImm(NumLPads & 0xFFFF)
10868 unsigned VReg2 = VReg1;
10869 if ((NumLPads & 0xFFFF0000) != 0) {
10870 VReg2 =
MRI->createVirtualRegister(TRC);
10871 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10877 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
10883 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
10888 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10889 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
10893 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10894 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
10901 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
10905 }
else if (Subtarget->isThumb()) {
10906 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10907 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
10913 if (NumLPads < 256) {
10914 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
10919 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10924 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
10925 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
10927 Register VReg1 =
MRI->createVirtualRegister(TRC);
10928 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
10932 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
10938 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
10943 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10944 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
10950 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10951 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
10955 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10956 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
10962 MachineMemOperand *JTMMOLd =
10966 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10967 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
10973 unsigned NewVReg6 = NewVReg5;
10974 if (IsPositionIndependent) {
10975 NewVReg6 =
MRI->createVirtualRegister(TRC);
10976 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
10983 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
10987 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10988 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
10994 if (NumLPads < 256) {
10995 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
10999 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11000 Register VReg1 =
MRI->createVirtualRegister(TRC);
11001 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11002 .
addImm(NumLPads & 0xFFFF)
11005 unsigned VReg2 = VReg1;
11006 if ((NumLPads & 0xFFFF0000) != 0) {
11007 VReg2 =
MRI->createVirtualRegister(TRC);
11008 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11014 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11019 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11024 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11025 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11027 Register VReg1 =
MRI->createVirtualRegister(TRC);
11028 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11033 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11044 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11045 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11050 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11051 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11055 MachineMemOperand *JTMMOLd =
11058 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11059 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11066 if (IsPositionIndependent) {
11067 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11072 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11079 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11080 for (MachineBasicBlock *CurMBB : LPadList) {
11081 if (SeenMBBs.
insert(CurMBB).second)
11088 for (MachineBasicBlock *BB : InvokeBBs) {
11092 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11093 while (!Successors.empty()) {
11094 MachineBasicBlock *SMBB = Successors.pop_back_val();
11096 BB->removeSuccessor(SMBB);
11102 BB->normalizeSuccProbs();
11109 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11110 if (!
II->isCall())
continue;
11112 DenseSet<unsigned> DefRegs;
11114 OI =
II->operands_begin(), OE =
II->operands_end();
11116 if (!OI->isReg())
continue;
11117 DefRegs.
insert(OI->getReg());
11120 MachineInstrBuilder MIB(*MF, &*
II);
11122 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11123 unsigned Reg = SavedRegs[i];
11124 if (Subtarget->isThumb2() &&
11125 !ARM::tGPRRegClass.contains(
Reg) &&
11126 !ARM::hGPRRegClass.contains(
Reg))
11128 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11130 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11142 for (MachineBasicBlock *MBBLPad : MBBLPads)
11143 MBBLPad->setIsEHPad(
false);
11146 MI.eraseFromParent();
11159static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11161 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11162 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11164 return LdSize == 4 ? ARM::tLDRi
11165 : LdSize == 2 ? ARM::tLDRHi
11166 : LdSize == 1 ? ARM::tLDRBi : 0;
11168 return LdSize == 4 ? ARM::t2LDR_POST
11169 : LdSize == 2 ? ARM::t2LDRH_POST
11170 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11171 return LdSize == 4 ? ARM::LDR_POST_IMM
11172 : LdSize == 2 ? ARM::LDRH_POST
11173 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11178static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11180 return StSize == 16 ? ARM::VST1q32wb_fixed
11181 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11183 return StSize == 4 ? ARM::tSTRi
11184 : StSize == 2 ? ARM::tSTRHi
11185 : StSize == 1 ? ARM::tSTRBi : 0;
11187 return StSize == 4 ? ARM::t2STR_POST
11188 : StSize == 2 ? ARM::t2STRH_POST
11189 : StSize == 1 ? ARM::t2STRB_POST : 0;
11190 return StSize == 4 ? ARM::STR_POST_IMM
11191 : StSize == 2 ? ARM::STRH_POST
11192 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11199 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11200 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11201 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11202 assert(LdOpc != 0 &&
"Should have a load opcode");
11209 }
else if (IsThumb1) {
11215 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11220 }
else if (IsThumb2) {
11240 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11241 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11242 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11243 assert(StOpc != 0 &&
"Should have a store opcode");
11245 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11250 }
else if (IsThumb1) {
11257 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11262 }
else if (IsThumb2) {
11263 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11269 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11284 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11290 unsigned SizeVal =
MI.getOperand(2).getImm();
11291 unsigned Alignment =
MI.getOperand(3).getImm();
11296 unsigned UnitSize = 0;
11297 const TargetRegisterClass *TRC =
nullptr;
11298 const TargetRegisterClass *VecTRC =
nullptr;
11300 bool IsThumb1 = Subtarget->isThumb1Only();
11301 bool IsThumb2 = Subtarget->isThumb2();
11302 bool IsThumb = Subtarget->isThumb();
11304 if (Alignment & 1) {
11306 }
else if (Alignment & 2) {
11311 Subtarget->hasNEON()) {
11312 if ((Alignment % 16 == 0) && SizeVal >= 16)
11314 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11323 bool IsNeon = UnitSize >= 8;
11324 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11326 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11327 : UnitSize == 8 ? &ARM::DPRRegClass
11330 unsigned BytesLeft = SizeVal % UnitSize;
11331 unsigned LoopSize = SizeVal - BytesLeft;
11333 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11337 unsigned srcIn = src;
11338 unsigned destIn = dest;
11339 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11340 Register srcOut =
MRI.createVirtualRegister(TRC);
11341 Register destOut =
MRI.createVirtualRegister(TRC);
11342 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11344 IsThumb1, IsThumb2);
11346 IsThumb1, IsThumb2);
11354 for (
unsigned i = 0; i < BytesLeft; i++) {
11355 Register srcOut =
MRI.createVirtualRegister(TRC);
11356 Register destOut =
MRI.createVirtualRegister(TRC);
11357 Register scratch =
MRI.createVirtualRegister(TRC);
11359 IsThumb1, IsThumb2);
11361 IsThumb1, IsThumb2);
11365 MI.eraseFromParent();
11391 MF->
insert(It, loopMBB);
11392 MF->
insert(It, exitMBB);
11395 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11405 Register varEnd =
MRI.createVirtualRegister(TRC);
11406 if (Subtarget->useMovt()) {
11407 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11410 }
else if (Subtarget->genExecuteOnly()) {
11411 assert(IsThumb &&
"Non-thumb expected to have used movt");
11420 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11421 MachineMemOperand *CPMMO =
11445 MachineBasicBlock *entryBB = BB;
11447 Register varLoop =
MRI.createVirtualRegister(TRC);
11448 Register varPhi =
MRI.createVirtualRegister(TRC);
11449 Register srcLoop =
MRI.createVirtualRegister(TRC);
11450 Register srcPhi =
MRI.createVirtualRegister(TRC);
11451 Register destLoop =
MRI.createVirtualRegister(TRC);
11452 Register destPhi =
MRI.createVirtualRegister(TRC);
11460 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11466 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11468 IsThumb1, IsThumb2);
11470 IsThumb1, IsThumb2);
11474 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11480 MachineInstrBuilder MIB =
11482 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11491 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11500 auto StartOfExit = exitMBB->
begin();
11504 unsigned srcIn = srcLoop;
11505 unsigned destIn = destLoop;
11506 for (
unsigned i = 0; i < BytesLeft; i++) {
11507 Register srcOut =
MRI.createVirtualRegister(TRC);
11508 Register destOut =
MRI.createVirtualRegister(TRC);
11509 Register scratch =
MRI.createVirtualRegister(TRC);
11510 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11511 IsThumb1, IsThumb2);
11512 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11513 IsThumb1, IsThumb2);
11518 MI.eraseFromParent();
11526 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11529 assert(Subtarget->isTargetWindows() &&
11530 "__chkstk is only supported on Windows");
11531 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11551 switch (TM.getCodeModel()) {
11593 MI.eraseFromParent();
11602 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11617 .
addReg(
MI.getOperand(0).getReg())
11625 MI.eraseFromParent();
11649 if (miI == BB->
end()) {
11651 if (Succ->isLiveIn(ARM::CPSR))
11657 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11669 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11670 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11676 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11677 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11683 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11684 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11687 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11688 .
addUse(TotalIterationsReg)
11695 return TotalIterationsReg;
11706 Register TotalIterationsReg,
bool IsMemcpy) {
11713 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11714 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11715 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11723 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11724 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11725 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11732 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11733 Register RemainingLoopIterationsReg =
11734 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11735 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11736 .
addUse(TotalIterationsReg)
11738 .
addUse(RemainingLoopIterationsReg)
11742 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11743 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11744 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11745 .
addUse(ElementCountReg)
11747 .
addUse(RemainingElementsReg)
11751 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11752 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11753 .
addUse(PredCounterPhiReg)
11758 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11759 .
addUse(PredCounterPhiReg)
11767 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11768 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11777 SrcValueReg = OpSrcReg;
11779 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11790 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11791 .
addUse(LoopCounterPhiReg)
11794 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11795 .
addUse(RemainingLoopIterationsReg)
11813 "Invalid call instruction for a KCFI check");
11816 switch (
MBBI->getOpcode()) {
11819 case ARM::BLX_pred:
11820 case ARM::BLX_noip:
11821 case ARM::BLX_pred_noip:
11823 TargetOp = &
MBBI->getOperand(0);
11825 case ARM::TCRETURNri:
11826 case ARM::TCRETURNrinotr12:
11827 case ARM::TAILJMPr:
11828 case ARM::TAILJMPr4:
11829 TargetOp = &
MBBI->getOperand(0);
11835 case ARM::tBLXr_noip:
11836 case ARM::tBX_CALL:
11837 TargetOp = &
MBBI->getOperand(2);
11840 case ARM::tTAILJMPr:
11841 TargetOp = &
MBBI->getOperand(0);
11847 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11851 unsigned KCFICheckOpcode;
11852 if (Subtarget->isThumb()) {
11853 if (Subtarget->isThumb2()) {
11854 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11856 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11859 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11873 bool isThumb2 = Subtarget->isThumb2();
11874 switch (
MI.getOpcode()) {
11881 case ARM::tLDR_postidx: {
11885 .
add(
MI.getOperand(2))
11886 .
add(
MI.getOperand(3))
11887 .
add(
MI.getOperand(4))
11888 .
add(
MI.getOperand(0))
11890 MI.eraseFromParent();
11894 case ARM::MVE_MEMCPYLOOPINST:
11895 case ARM::MVE_MEMSETLOOPINST: {
11925 Register OpDestReg =
MI.getOperand(0).getReg();
11926 Register OpSrcReg =
MI.getOperand(1).getReg();
11927 Register OpSizeReg =
MI.getOperand(2).getReg();
11947 if (TpExit == BB) {
11949 "block containing memcpy/memset Pseudo");
11962 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
11964 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
11967 Properties.resetNoPHIs();
11979 MI.eraseFromParent();
11989 case ARM::t2STR_preidx:
11990 MI.setDesc(
TII->get(ARM::t2STR_PRE));
11992 case ARM::t2STRB_preidx:
11993 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
11995 case ARM::t2STRH_preidx:
11996 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
11999 case ARM::STRi_preidx:
12000 case ARM::STRBi_preidx: {
12001 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12002 : ARM::STRB_PRE_IMM;
12004 unsigned Offset =
MI.getOperand(4).getImm();
12012 .
add(
MI.getOperand(0))
12013 .
add(
MI.getOperand(1))
12014 .
add(
MI.getOperand(2))
12016 .
add(
MI.getOperand(5))
12017 .
add(
MI.getOperand(6))
12019 MI.eraseFromParent();
12022 case ARM::STRr_preidx:
12023 case ARM::STRBr_preidx:
12024 case ARM::STRH_preidx: {
12026 switch (
MI.getOpcode()) {
12028 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12029 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12030 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12035 MI.eraseFromParent();
12039 case ARM::tMOVCCr_pseudo: {
12057 F->insert(It, copy0MBB);
12058 F->insert(It, sinkMBB);
12061 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12067 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12083 .
addImm(
MI.getOperand(3).getImm())
12084 .
addReg(
MI.getOperand(4).getReg());
12099 .
addReg(
MI.getOperand(1).getReg())
12101 .
addReg(
MI.getOperand(2).getReg())
12104 MI.eraseFromParent();
12109 case ARM::BCCZi64: {
12115 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12120 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12124 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12130 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12134 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12144 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12153 MI.eraseFromParent();
12157 case ARM::Int_eh_sjlj_setjmp:
12158 case ARM::Int_eh_sjlj_setjmp_nofp:
12159 case ARM::tInt_eh_sjlj_setjmp:
12160 case ARM::t2Int_eh_sjlj_setjmp:
12161 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12164 case ARM::Int_eh_sjlj_setup_dispatch:
12165 EmitSjLjDispatchBlock(
MI, BB);
12167 case ARM::COPY_STRUCT_BYVAL_I32:
12169 return EmitStructByval(
MI, BB);
12170 case ARM::WIN__CHKSTK:
12171 return EmitLowered__chkstk(
MI, BB);
12172 case ARM::WIN__DBZCHK:
12173 return EmitLowered__dbzchk(
MI, BB);
12189 if (!
Node->hasAnyUseOfValue(0)) {
12190 MI.getOperand(0).setIsDead(
true);
12192 if (!
Node->hasAnyUseOfValue(1)) {
12193 MI.getOperand(1).setIsDead(
true);
12197 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12198 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12199 : &ARM::GPRRegClass);
12206 if (
MI.getOpcode() == ARM::MEMCPY) {
12227 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12228 &&
"converted opcode should be the same except for cc_out"
12229 " (and, on Thumb1, pred)");
12237 if (Subtarget->isThumb1Only()) {
12238 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12239 MI.addOperand(
MI.getOperand(1));
12240 MI.removeOperand(1);
12244 for (
unsigned i =
MI.getNumOperands(); i--;) {
12246 if (
op.isReg() &&
op.isUse()) {
12249 MI.tieOperands(DefIdx, i);
12257 ccOutIdx =
MCID->getNumOperands() - 1;
12259 ccOutIdx =
MCID->getNumOperands() - 1;
12263 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12264 assert(!NewOpc &&
"Optional cc_out operand required");
12269 bool definesCPSR =
false;
12270 bool deadCPSR =
false;
12271 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12275 definesCPSR =
true;
12278 MI.removeOperand(i);
12282 if (!definesCPSR) {
12283 assert(!NewOpc &&
"Optional cc_out operand required");
12286 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12288 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12289 "expect uninitialized optional cc_out operand");
12291 if (!Subtarget->isThumb1Only())
12327 switch (
N->getOpcode()) {
12328 default:
return false;
12330 CC =
N->getOperand(0);
12352 EVT VT =
N->getValueType(0);
12353 CC =
N->getOperand(0);
12400 EVT VT =
N->getValueType(0);
12403 bool SwapSelectOps;
12405 NonConstantVal, DAG))
12411 OtherOp, NonConstantVal);
12417 CCOp, TrueVal, FalseVal);
12437 if (
N->getOpcode() == ARMISD::VUZP)
12441 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12456 if (!
N->getValueType(0).is64BitVector())
12464 EVT VT =
N->getValueType(0);
12503 EVT VT =
N->getValueType(0);
12509 Opcode = Intrinsic::arm_neon_vpaddls;
12511 Opcode = Intrinsic::arm_neon_vpaddlu;
12539 EVT VT =
N->getValueType(0);
12554 unsigned nextIndex = 0;
12605 Ops.push_back(Vec);
12622 return DAG.
getNode(ExtOp, dl, VT, tmp);
12653 if (SRA.getOpcode() !=
ISD::SRA) {
12660 if (Const->getZExtValue() != 31)
12665 if (SRA.getOperand(0) !=
Mul)
12669 SDLoc dl(AddcNode);
12670 unsigned Opcode = 0;
12675 Opcode = ARMISD::SMLALBB;
12676 Op0 =
Mul.getOperand(0);
12677 Op1 =
Mul.getOperand(1);
12679 Opcode = ARMISD::SMLALBT;
12680 Op0 =
Mul.getOperand(0);
12681 Op1 =
Mul.getOperand(1).getOperand(0);
12683 Opcode = ARMISD::SMLALTB;
12684 Op0 =
Mul.getOperand(0).getOperand(0);
12685 Op1 =
Mul.getOperand(1);
12687 Opcode = ARMISD::SMLALTT;
12688 Op0 =
Mul->getOperand(0).getOperand(0);
12689 Op1 =
Mul->getOperand(1).getOperand(0);
12705 SDValue resNode(AddcNode, 0);
12733 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12734 "Expect an ADDE or SUBE");
12738 "ADDE node has the wrong inputs");
12742 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12743 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12744 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12745 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12757 "Expect ADDC with two result values. First: i32");
12761 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12777 bool IsLeftOperandMUL =
false;
12782 IsLeftOperandMUL =
true;
12793 SDValue *LowAddSub =
nullptr;
12796 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12799 if (IsLeftOperandMUL)
12800 HiAddSub = &AddeSubeOp1;
12802 HiAddSub = &AddeSubeOp0;
12807 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12808 LoMul = &AddcSubcOp0;
12809 LowAddSub = &AddcSubcOp1;
12811 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12812 LoMul = &AddcSubcOp1;
12813 LowAddSub = &AddcSubcOp0;
12821 if (AddcSubcNode == HiAddSub->getNode() ||
12837 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12842 Ops.push_back(*HiAddSub);
12843 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12844 FinalOpc = ARMISD::SMMLSR;
12846 FinalOpc = ARMISD::SMMLAR;
12851 return SDValue(AddeSubeNode, 0);
12852 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12858 Ops.push_back(*LowAddSub);
12859 Ops.push_back(*HiAddSub);
12872 return SDValue(AddeSubeNode, 0);
12884 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12889 if (AddcNode->
getOpcode() != ARMISD::ADDC)
12893 SDNode *UmlalNode =
nullptr;
12932 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12937 SDNode* AddcNode =
N->getOperand(2).getNode();
12938 SDNode* AddeNode =
N->getOperand(3).getNode();
12939 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
12940 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
12946 {N->getOperand(0), N->getOperand(1),
12947 AddcNode->getOperand(0), AddcNode->getOperand(1)});
12957 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
12961 if (
LHS->getOpcode() == ARMISD::ADDE &&
12971 int32_t imm =
C->getSExtValue();
12972 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
12975 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
12977 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
12992 int64_t imm =
C->getSExtValue();
13001 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13003 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13004 N->getOperand(0),
RHS,
N->getOperand(2));
13016 if (!Subtarget->hasMVEIntegerOps())
13029 SetCC =
N->getOperand(0);
13033 TrueVal =
N->getOperand(1);
13034 FalseVal =
N->getOperand(2);
13036 LHS =
N->getOperand(0);
13037 RHS =
N->getOperand(1);
13039 TrueVal =
N->getOperand(2);
13040 FalseVal =
N->getOperand(3);
13045 unsigned int Opcode = 0;
13046 if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMIN ||
13047 FalseVal->getOpcode() == ISD::VECREDUCE_UMIN) &&
13049 Opcode = ARMISD::VMINVu;
13052 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMIN ||
13053 FalseVal->getOpcode() == ISD::VECREDUCE_SMIN) &&
13055 Opcode = ARMISD::VMINVs;
13058 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMAX ||
13059 FalseVal->getOpcode() == ISD::VECREDUCE_UMAX) &&
13061 Opcode = ARMISD::VMAXVu;
13064 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMAX ||
13065 FalseVal->getOpcode() == ISD::VECREDUCE_SMAX) &&
13067 Opcode = ARMISD::VMAXVs;
13074 switch (TrueVal->getOpcode()) {
13075 case ISD::VECREDUCE_UMIN:
13076 case ISD::VECREDUCE_SMIN:
13077 case ISD::VECREDUCE_UMAX:
13078 case ISD::VECREDUCE_SMAX:
13093 if (TrueVal !=
LHS || FalseVal !=
RHS)
13096 EVT LeftType =
LHS->getValueType(0);
13097 EVT RightType =
RHS->getValueType(0);
13100 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13104 if (VectorScalarType != MVT::i32)
13112 if (VectorScalarType != MVT::i32)
13125 EVT VT =
N->getValueType(0);
13133 Shft =
N->getOperand(0);
13140 Cmp.getOperand(0) !=
N->getOperand(1) ||
13141 Cmp.getOperand(1) !=
N->getOperand(2))
13143 Shft =
N->getOperand(1);
13155 ScalarType = MVT::i8;
13158 case (1 << 15) - 1:
13159 ScalarType = MVT::i16;
13162 case (1ULL << 31) - 1:
13163 ScalarType = MVT::i32;
13194 unsigned LegalLanes = 128 / (ShftAmt + 1);
13206 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13207 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13208 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13209 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13218 for (
unsigned I = 0;
I < NumParts; ++
I) {
13225 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13235 if (!Subtarget->hasMVEIntegerOps())
13250 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13260 if (!Const || !Const->isOne())
13278 EVT VT =
N->getValueType(0);
13280 if (!Subtarget->hasMVEIntegerOps() ||
13309 Opc = Intrinsic::arm_mve_vctp64;
13312 Opc = Intrinsic::arm_mve_vctp32;
13315 Opc = Intrinsic::arm_mve_vctp16;
13318 Opc = Intrinsic::arm_mve_vctp8;
13372 EVT VT =
N->getValueType(0);
13378 switch (
Op.getOpcode()) {
13379 case ISD::VECREDUCE_ADD:
13380 case ARMISD::VADDVs:
13381 case ARMISD::VADDVu:
13382 case ARMISD::VMLAVs:
13383 case ARMISD::VMLAVu:
13403 unsigned N0RedOp = 0;
13410 unsigned N1RedOp = 0;
13424 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13426 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13433 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13457 if (!BaseLocDecomp0.getBase() ||
13458 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13459 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13461 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13463 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13473 if (IsBefore < 0) {
13476 }
else if (IsBefore > 0) {
13489 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13499 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13509 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13511 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13518 if (!Subtarget->hasMVEIntegerOps())
13524 EVT VT =
N->getValueType(0);
13529 if (VT != MVT::i64)
13540 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13560 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13569 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13571 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13573 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13575 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13577 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13579 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13581 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13583 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13585 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13587 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13589 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13591 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13593 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13595 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13597 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13599 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13609 "Expected shift op");
13611 SDValue ShiftLHS =
N->getOperand(0);
13625 if (Subtarget->isThumb1Only()) {
13636 if (Const->getAPIntValue().ult(256))
13639 Const->getAPIntValue().sgt(-256))
13655 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13656 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13657 "Expected XOR(SHIFT) pattern");
13662 if (XorC && ShiftC) {
13663 unsigned MaskIdx, MaskLen;
13664 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13665 unsigned ShiftAmt = ShiftC->getZExtValue();
13666 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13667 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13668 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13669 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13679 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13681 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13682 "Expected shift-shift mask");
13684 if (!Subtarget->isThumb1Only())
13687 EVT VT =
N->getValueType(0);
13695 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13697 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13702 if (!Subtarget->hasNEON()) {
13703 if (Subtarget->isThumb1Only())
13717 return Subtarget->hasVFP2Base();
13719 return Subtarget->hasVFP2Base();
13721 return Subtarget->hasFP64();
13724 return Subtarget->hasMVEFloatOps();
13753 if (ST->isThumb() && ST->isThumb1Only())
13757 for (
auto *U :
N->users()) {
13758 switch(U->getOpcode()) {
13776 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13777 U->getOperand(1).getOpcode() ==
ISD::SHL)
13787 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13794 if (!C1ShlC2 || !C2)
13797 APInt C2Int = C2->getAPIntValue();
13798 APInt C1Int = C1ShlC2->getAPIntValue();
13800 if (C2Int.
uge(C2Width))
13806 if ((C1Int & Mask) != C1Int)
13813 auto LargeImm = [](
const APInt &Imm) {
13814 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13815 return Imm.getBitWidth() - Zeros > 8;
13818 if (LargeImm(C1Int) || LargeImm(C2Int))
13830 SHL.dump();
N->dump());
13933 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
13954 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
13975 if (!Subtarget->hasVMLxForwarding())
13994 EVT VT =
N->getValueType(0);
14005 EVT VT =
N->getValueType(0);
14006 if (VT != MVT::v2i64)
14017 return Op->getOperand(0);
14030 if (
And->getOpcode() == ISD::BITCAST)
14031 And =
And->getOperand(0);
14035 if (Mask->getOpcode() == ISD::BITCAST)
14036 Mask = Mask->getOperand(0);
14039 Mask.getValueType() != MVT::v4i32)
14045 return And->getOperand(0);
14050 if (
SDValue Op0 = IsSignExt(N0)) {
14051 if (
SDValue Op1 = IsSignExt(N1)) {
14052 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14053 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14054 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14057 if (
SDValue Op0 = IsZeroExt(N0)) {
14058 if (
SDValue Op1 = IsZeroExt(N1)) {
14059 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14060 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14061 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14073 EVT VT =
N->getValueType(0);
14074 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14085 if (VT != MVT::i32)
14092 int64_t MulAmt =
C->getSExtValue();
14095 ShiftAmt = ShiftAmt & (32 - 1);
14100 MulAmt >>= ShiftAmt;
14161 if (
N->getValueType(0) != MVT::i32)
14170 if (C1 == 255 || C1 == 65535)
14173 SDNode *N0 =
N->getOperand(0).getNode();
14187 if (!C2 || C2 >= 32)
14231 if (Trailing == C2 && C2 + C3 < 32) {
14244 if (Leading == C2 && C2 + C3 < 32) {
14272 EVT VT =
N->getValueType(0);
14276 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14279 APInt SplatBits, SplatUndef;
14280 unsigned SplatBitSize;
14282 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14283 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14284 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14285 SplatBitSize == 64) {
14292 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14294 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14319 if (!Subtarget->hasV6Ops() ||
14320 (Subtarget->isThumb() &&
14321 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14324 SDValue SRL = OR->getOperand(0);
14325 SDValue SHL = OR->getOperand(1);
14328 SRL = OR->getOperand(1);
14329 SHL = OR->getOperand(0);
14336 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14340 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14341 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14342 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14361 unsigned Opcode = 0;
14362 if (
isS16(OpS16, DAG))
14363 Opcode = ARMISD::SMULWB;
14365 Opcode = ARMISD::SMULWT;
14380 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14383 EVT VT =
N->getValueType(0);
14398 if (VT != MVT::i32)
14411 if (Mask == 0xffff)
14418 if ((Val & ~Mask) != Val)
14424 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14443 (Mask == ~Mask2)) {
14446 if (Subtarget->hasDSP() &&
14447 (Mask == 0xffff || Mask == 0xffff0000))
14453 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14460 (~Mask == Mask2)) {
14463 if (Subtarget->hasDSP() &&
14464 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14520 if (
N->getOpcode() == ARMISD::VCMP)
14522 else if (
N->getOpcode() == ARMISD::VCMPZ)
14530 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14537 EVT VT =
N->getValueType(0);
14542 auto IsFreelyInvertable = [&](
SDValue V) {
14543 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14549 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14565 EVT VT =
N->getValueType(0);
14571 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14572 VT == MVT::v8i1 || VT == MVT::v16i1))
14575 APInt SplatBits, SplatUndef;
14576 unsigned SplatBitSize;
14578 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14579 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14580 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14581 SplatBitSize == 64) {
14588 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14590 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14617 unsigned SplatBitSize;
14620 APInt SplatBits0, SplatBits1;
14624 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14625 HasAnyUndefs) && !HasAnyUndefs) {
14626 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14627 HasAnyUndefs) && !HasAnyUndefs) {
14632 SplatBits0 == ~SplatBits1) {
14640 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14662 EVT VT =
N->getValueType(0);
14677 if (Subtarget->hasMVEIntegerOps()) {
14705 assert(
N->getOpcode() == ARMISD::BFI);
14708 ToMask =
~N->getConstantOperandAPInt(2);
14728 unsigned LastActiveBitInA =
A.countr_zero();
14729 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14730 return LastActiveBitInA - 1 == FirstActiveBitInB;
14735 APInt ToMask, FromMask;
14740 if (V.getOpcode() != ARMISD::BFI)
14743 APInt NewToMask, NewFromMask;
14745 if (NewFrom != From)
14749 if ((NewToMask & ToMask).getBoolValue())
14774 unsigned InvMask =
N->getConstantOperandVal(2);
14778 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14779 "undefined behavior");
14780 unsigned Mask = (1u << Width) - 1;
14782 if ((Mask & (~Mask2)) == 0)
14784 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14791 APInt ToMask1, FromMask1;
14794 APInt ToMask2, FromMask2;
14800 APInt NewFromMask = FromMask1 | FromMask2;
14801 APInt NewToMask = ToMask1 | ToMask2;
14803 EVT VT =
N->getValueType(0);
14806 if (NewFromMask[0] == 0)
14809 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
14817 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
14818 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14819 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14821 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14825 EVT VT =
N->getValueType(0);
14828 N->getOperand(1),
N->getOperand(2));
14840 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
14842 SDValue CSInc = Cmp->getOperand(0);
14852 if (CSInc.
getOpcode() == ARMISD::CSINC &&
14892 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
14893 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
14896 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
14898 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
14911 SDValue InDouble =
N->getOperand(0);
14912 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
14926 SDValue BasePtr = LD->getBasePtr();
14928 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
14929 LD->getAlign(), LD->getMemOperand()->getFlags());
14935 LD->getPointerInfo().getWithOffset(4),
14937 LD->getMemOperand()->getFlags());
14953 bool BVSwap = BV.
getOpcode() == ISD::BITCAST;
14956 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
14958 BVSwap = BV.
getOpcode() == ISD::BITCAST;
14970 if (!Subtarget->
isLittle() && BVSwap)
14988 if (!Subtarget->
isLittle() && BVSwap)
15007 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15020 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15031 if (Op0->
getOpcode() == ISD::BITCAST) {
15033 if (Copy.getValueType() == MVT::f32 &&
15035 bool HasGlue = Copy->getNumOperands() == 3;
15036 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15037 HasGlue ? Copy->getOperand(2) :
SDValue()};
15038 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15057 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15058 LN0->getMemoryVT() == MVT::i16) {
15061 LN0->getBasePtr(), LN0->getMemOperand());
15079 EVT VT =
N->getValueType(0);
15113 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15114 for (
unsigned i = 0; i < NumElts; ++i) {
15115 SDNode *Elt =
N->getOperand(i).getNode();
15132 if (
N->getNumOperands() == 2)
15138 EVT VT =
N->getValueType(0);
15144 for (
unsigned i = 0; i < NumElts; ++i) {
15145 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(i));
15152 return DAG.
getNode(ISD::BITCAST, dl, VT, BV);
15170 EVT VT =
N->getValueType(0);
15178 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15182 if (
Use->getOpcode() != ISD::BITCAST ||
15183 Use->getValueType(0).isFloatingPoint())
15191 unsigned NumOfBitCastedElts = 0;
15193 unsigned NumOfRelevantElts = NumElts;
15194 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15196 if (Elt->
getOpcode() == ISD::BITCAST) {
15199 ++NumOfBitCastedElts;
15203 --NumOfRelevantElts;
15207 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15225 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15229 if (V.getOpcode() == ISD::BITCAST &&
15230 V->getOperand(0).getValueType() == MVT::i32)
15232 V = V.getOperand(0);
15241 Vec = DAG.
getNode(ISD::BITCAST, dl, VT, Vec);
15249 EVT VT =
N->getValueType(0);
15254 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15256 if (
Op->getOperand(0).getValueType() == VT)
15257 return Op->getOperand(0);
15258 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15265 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15272 if (
Op.getValueType() == MVT::i32) {
15283 EVT VT =
N->getValueType(0);
15288 if (ST->isLittle())
15289 return DAG.
getNode(ISD::BITCAST, dl, VT,
Op);
15292 if (
Op.getValueType() == VT)
15299 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15301 if (
Op->getOperand(0).getValueType() == VT)
15302 return Op->getOperand(0);
15303 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15311 if (!Subtarget->hasMVEIntegerOps())
15314 EVT VT =
N->getValueType(0);
15322 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15328 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15332 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15345 EVT VT =
N->getValueType(0);
15346 SDNode *Elt =
N->getOperand(1).getNode();
15355 SDValue Vec = DAG.
getNode(ISD::BITCAST, dl, FloatVT,
N->getOperand(0));
15356 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(1));
15361 Vec, V,
N->getOperand(2));
15362 return DAG.
getNode(ISD::BITCAST, dl, VT, InsElt);
15371 EVT VT =
N->getValueType(0);
15379 if (Ext.getOpcode() == ISD::BITCAST &&
15380 Ext.getOperand(0).getValueType() == MVT::f32)
15381 Ext = Ext.getOperand(0);
15384 Ext.getConstantOperandVal(1) % 2 != 0)
15386 if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() ==
ISD::SINT_TO_FP ||
15390 SDValue Op0 = Ext.getOperand(0);
15393 unsigned Lane = Ext.getConstantOperandVal(1);
15399 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15400 isa<ConstantSDNode>(V->getOperand(1)) &&
15401 V->getConstantOperandVal(1) == Lane + 1 &&
15402 V->getOperand(0).getResNo() == ResNo;
15404 if (OtherIt == Op0->
users().
end())
15409 SDValue OtherExt(*OtherIt, 0);
15421 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15422 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15424 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15434 EVT VT =
N->getValueType(0);
15438 if (Op0->
getOpcode() == ARMISD::VDUP) {
15440 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15441 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15442 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15443 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15444 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15447 while (
X.getValueType() != VT &&
X->getOpcode() == ISD::BITCAST)
15448 X =
X->getOperand(0);
15449 if (
X.getValueType() == VT)
15457 return Op0.
getOperand(
N->getConstantOperandVal(1));
15467 unsigned Offset =
N->getConstantOperandVal(1);
15469 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15479 unsigned Idx =
N->getConstantOperandVal(1);
15493 EVT VT =
N->getValueType(0);
15496 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15498 Op.getOperand(0).getValueType().getScalarType())
15499 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15508 SDValue SubVec =
N->getOperand(1);
15509 uint64_t IdxVal =
N->getConstantOperandVal(2);
15520 if (IdxVal == 0 && Vec.
isUndef())
15526 (IdxVal != 0 && IdxVal != NumSubElts))
15557 ARMISD::VMOVN,
DL, VT,
15563 ARMISD::VMOVN,
DL, VT,
15599 EVT VT =
N->getValueType(0);
15610 unsigned HalfElts = NumElts/2;
15612 for (
unsigned n = 0; n < NumElts; ++n) {
15615 if (MaskElt < (
int)HalfElts)
15617 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15618 NewElt = HalfElts + MaskElt - NumElts;
15661 bool SimpleConstIncOnly,
15669 bool isLoadOp =
true;
15670 bool isLaneOp =
false;
15673 bool hasAlignment =
true;
15674 unsigned NewOpc = 0;
15675 unsigned NumVecs = 0;
15676 if (
Target.isIntrinsic) {
15677 unsigned IntNo =
N->getConstantOperandVal(1);
15681 case Intrinsic::arm_neon_vld1:
15685 case Intrinsic::arm_neon_vld2:
15689 case Intrinsic::arm_neon_vld3:
15693 case Intrinsic::arm_neon_vld4:
15697 case Intrinsic::arm_neon_vld1x2:
15700 hasAlignment =
false;
15702 case Intrinsic::arm_neon_vld1x3:
15705 hasAlignment =
false;
15707 case Intrinsic::arm_neon_vld1x4:
15710 hasAlignment =
false;
15712 case Intrinsic::arm_neon_vld2dup:
15716 case Intrinsic::arm_neon_vld3dup:
15720 case Intrinsic::arm_neon_vld4dup:
15724 case Intrinsic::arm_neon_vld2lane:
15729 case Intrinsic::arm_neon_vld3lane:
15734 case Intrinsic::arm_neon_vld4lane:
15739 case Intrinsic::arm_neon_vst1:
15744 case Intrinsic::arm_neon_vst2:
15745 NewOpc = ARMISD::VST2_UPD;
15749 case Intrinsic::arm_neon_vst3:
15754 case Intrinsic::arm_neon_vst4:
15755 NewOpc = ARMISD::VST4_UPD;
15759 case Intrinsic::arm_neon_vst2lane:
15765 case Intrinsic::arm_neon_vst3lane:
15771 case Intrinsic::arm_neon_vst4lane:
15777 case Intrinsic::arm_neon_vst1x2:
15781 hasAlignment =
false;
15783 case Intrinsic::arm_neon_vst1x3:
15787 hasAlignment =
false;
15789 case Intrinsic::arm_neon_vst1x4:
15793 hasAlignment =
false;
15798 switch (
N->getOpcode()) {
15834 VecTy =
N->getValueType(0);
15835 }
else if (
Target.isIntrinsic) {
15836 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
15839 "Node has to be a load, a store, or an intrinsic!");
15840 VecTy =
N->getOperand(1).getValueType();
15848 if (isLaneOp || isVLDDUPOp)
15851 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
15857 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
15866 EVT AlignedVecTy = VecTy;
15886 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
15887 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
15898 Alignment =
Align(1);
15904 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
15906 for (n = 0; n < NumResultVecs; ++n)
15907 Tys[n] = AlignedVecTy;
15908 Tys[n++] = MVT::i32;
15909 Tys[n] = MVT::Other;
15914 Ops.push_back(
N->getOperand(0));
15915 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
15920 Ops.push_back(StN->getValue());
15924 unsigned LastOperand =
15925 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
15926 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
15927 Ops.push_back(
N->getOperand(i));
15935 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::STORE) {
15937 StVal = DAG.
getNode(ISD::BITCAST, dl, AlignedVecTy, StVal);
15946 for (
unsigned i = 0; i < NumResultVecs; ++i)
15951 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::LOAD) {
15952 SDValue &LdVal = NewResults[0];
15953 LdVal = DAG.
getNode(ISD::BITCAST, dl, VecTy, LdVal);
15988 switch (
N->getOpcode()) {
15992 *Ptr =
N->getOperand(0);
15993 *CInc =
N->getOperand(1);
16000 *Ptr =
N->getOperand(1);
16001 *CInc =
N->getOperand(2);
16020 const bool isStore =
N->getOpcode() == ISD::STORE;
16028 SDValue Addr =
N->getOperand(AddrOpIdx);
16039 unsigned ConstInc =
16044 if (BaseUpdates.
size() >= MaxBaseUpdates)
16064 unsigned UserOffset =
16067 if (!UserOffset || UserOffset <=
Offset)
16070 unsigned NewConstInc = UserOffset -
Offset;
16073 if (BaseUpdates.
size() >= MaxBaseUpdates)
16080 unsigned NumValidUpd = BaseUpdates.
size();
16081 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16092 return LHS.ConstInc <
RHS.ConstInc;
16121 unsigned IntNo =
N->getConstantOperandVal(1);
16122 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16124 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16147 bool isLoadOp =
true;
16148 unsigned NewOpc = 0;
16149 unsigned NumVecs = 0;
16153 case Intrinsic::arm_mve_vld2q:
16157 case Intrinsic::arm_mve_vld4q:
16161 case Intrinsic::arm_mve_vst2q:
16162 NewOpc = ARMISD::VST2_UPD;
16166 case Intrinsic::arm_mve_vst4q:
16167 NewOpc = ARMISD::VST4_UPD;
16176 VecTy =
N->getValueType(0);
16178 VecTy =
N->getOperand(3).getValueType();
16192 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16194 for (n = 0; n < NumResultVecs; ++n)
16196 Tys[n++] = MVT::i32;
16197 Tys[n] = MVT::Other;
16202 Ops.push_back(
N->getOperand(0));
16203 Ops.push_back(
N->getOperand(2));
16204 Ops.push_back(Inc);
16206 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16207 Ops.push_back(
N->getOperand(i));
16214 for (
unsigned i = 0; i < NumResultVecs; ++i)
16233 EVT VT =
N->getValueType(0);
16239 SDNode *VLD =
N->getOperand(0).getNode();
16242 unsigned NumVecs = 0;
16243 unsigned NewOpc = 0;
16245 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16248 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16251 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16263 if (
Use.getResNo() == NumVecs)
16266 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16267 VLDLaneNo !=
User->getConstantOperandVal(1))
16274 for (n = 0; n < NumVecs; ++n)
16276 Tys[n] = MVT::Other;
16286 unsigned ResNo =
Use.getResNo();
16288 if (ResNo == NumVecs)
16295 std::vector<SDValue> VLDDupResults;
16296 for (
unsigned n = 0; n < NumVecs; ++n)
16310 EVT VT =
N->getValueType(0);
16313 if (Subtarget->hasMVEIntegerOps()) {
16317 ExtractVT = MVT::i32;
16319 N->getOperand(0),
N->getOperand(1));
16330 while (
Op.getOpcode() == ISD::BITCAST)
16331 Op =
Op.getOperand(0);
16332 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16336 unsigned EltSize =
Op.getScalarValueSizeInBits();
16338 unsigned Imm =
Op.getConstantOperandVal(0);
16354 if (Subtarget->hasMVEIntegerOps()) {
16357 if (
Op.getValueType() == MVT::f32)
16358 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16359 DAG.
getNode(ISD::BITCAST, dl, MVT::i32,
Op));
16360 else if (
Op.getValueType() == MVT::f16)
16361 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16362 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16365 if (!Subtarget->hasNEON())
16372 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16373 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16374 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16379 LD->getMemoryVT(), LD->getMemOperand());
16390 EVT VT =
N->getValueType(0);
16412 assert(StVT != VT &&
"Cannot truncate to the same type");
16422 if (0 != (NumElems * FromEltSz) % ToEltSz)
16425 unsigned SizeRatio = FromEltSz / ToEltSz;
16430 NumElems * SizeRatio);
16436 for (
unsigned i = 0; i < NumElems; ++i)
16450 MVT StoreType = MVT::i8;
16452 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16472 for (
unsigned I = 0;
I <
E;
I++) {
16503 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16506 unsigned NumElements = 4;
16523 unsigned Off0 = Rev ? NumElts : 0;
16524 unsigned Off1 = Rev ? 0 : NumElts;
16526 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16527 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16529 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16537 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16557 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16568 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16572 NewToVT, Alignment, MMOFlags, AAInfo);
16605 unsigned NewOffset =
16613 NewToVT, Alignment, MMOFlags, AAInfo);
16635 {Extract.getOperand(0), Extract.getOperand(1)});
16666 if (Subtarget->hasNEON())
16670 if (Subtarget->hasMVEFloatOps())
16674 if (Subtarget->hasMVEIntegerOps()) {
16749 if (!Subtarget->hasNEON())
16753 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16761 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16763 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16764 uint32_t IntBits = IntTy.getSizeInBits();
16765 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16766 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16777 if (
C == -1 ||
C == 0 ||
C > 32)
16782 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16783 Intrinsic::arm_neon_vcvtfp2fxu;
16786 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16789 if (IntBits < FloatBits)
16797 if (!Subtarget->hasMVEFloatOps())
16805 EVT VT =
N->getValueType(0);
16810 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16811 if (
Op.getOpcode() != ISD::BITCAST ||
16812 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
16814 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16815 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16817 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16830 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
16841 EVT VT =
N->getValueType(0);
16844 if (!
N->getFlags().hasAllowReassociation())
16851 unsigned Opc =
A.getConstantOperandVal(0);
16852 if (
Opc != Intrinsic::arm_mve_vcmlaq)
16857 A.getOperand(3),
A.getOperand(4));
16889 if (!Subtarget->hasNEON())
16893 unsigned OpOpcode =
Op.getNode()->getOpcode();
16894 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
16898 SDValue ConstVec =
N->getOperand(1);
16902 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
16904 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
16905 uint32_t IntBits = IntTy.getSizeInBits();
16906 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16907 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16927 int32_t
C = IntVal.exactLogBase2();
16928 if (
C == -1 ||
C == 0 ||
C > 32)
16934 if (IntBits < FloatBits)
16936 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
16938 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
16939 : Intrinsic::arm_neon_vcvtfxu2fp;
16947 if (!ST->hasMVEIntegerOps())
16950 assert(
N->getOpcode() == ISD::VECREDUCE_ADD);
16951 EVT ResVT =
N->getValueType(0);
16979 EVT AVT =
A.getValueType();
16985 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
16986 EVT AVT =
A.getValueType();
16994 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
16995 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
16998 if (ExtTypeMatches(
A, ExtTypes))
16999 return ExtendIfNeeded(
A, ExtendCode);
17002 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17009 if (Ext->getOpcode() != ExtendCode)
17012 if (ExtTypeMatches(
A, ExtTypes))
17013 return ExtendIfNeeded(
A, ExtendCode);
17016 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17026 if (ResVT != RetTy)
17029 if (
Mul->getOpcode() == ExtendCode &&
17030 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17032 Mul =
Mul->getOperand(0);
17041 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17042 A = ExtendIfNeeded(
A, ExtendCode);
17043 B = ExtendIfNeeded(
B, ExtendCode);
17048 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17061 if (
Mul->getOpcode() == ExtendCode &&
17062 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17064 Mul =
Mul->getOperand(0);
17073 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17074 A = ExtendIfNeeded(
A, ExtendCode);
17075 B = ExtendIfNeeded(
B, ExtendCode);
17086 EVT VT =
Ops[0].getValueType();
17087 if (VT == MVT::v16i8) {
17088 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17089 "Unexpected illegal long reduction opcode");
17090 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17102 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17115 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17117 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17118 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17120 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17121 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17123 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17126 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17129 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17133 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17136 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17139 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17142 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17145 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17148 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17151 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17153 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17155 return Create64bitNode(ARMISD::VADDLVs, {
A});
17157 return Create64bitNode(ARMISD::VADDLVu, {
A});
17160 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17163 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17166 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17168 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17170 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17172 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17175 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17178 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17185 Op =
Op->getOperand(1);
17187 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17189 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17195 return DAG.
getNode(ISD::VECREDUCE_ADD, dl, ResVT, Ext);
17206 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17208 if (!Shuf || !Shuf->getOperand(1).isUndef())
17213 APInt SetElts(Mask.size(), 0);
17214 for (
int E : Mask) {
17222 if (
N->getNumOperands() != VecOp + 1) {
17224 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17230 if (
Op.getValueType().isVector())
17231 Ops.push_back(
Op.getOperand(0));
17242 unsigned IsTop =
N->getConstantOperandVal(2);
17249 if (Op0->
isUndef() && !IsTop)
17254 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17255 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17263 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17265 APInt Op0DemandedElts =
17266 IsTop ? Op1DemandedElts
17281 unsigned IsTop =
N->getConstantOperandVal(2);
17283 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17284 APInt Op0DemandedElts =
17296 EVT VT =
N->getValueType(0);
17303 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17304 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17308 LHS.getOperand(0),
RHS.getOperand(0));
17323 int ShiftAmt =
C->getSExtValue();
17324 if (ShiftAmt == 0) {
17330 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17331 unsigned NewOpcode =
17332 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17347 unsigned IntNo =
N->getConstantOperandVal(0);
17358 case Intrinsic::arm_neon_vshifts:
17359 case Intrinsic::arm_neon_vshiftu:
17360 case Intrinsic::arm_neon_vrshifts:
17361 case Intrinsic::arm_neon_vrshiftu:
17362 case Intrinsic::arm_neon_vrshiftn:
17363 case Intrinsic::arm_neon_vqshifts:
17364 case Intrinsic::arm_neon_vqshiftu:
17365 case Intrinsic::arm_neon_vqshiftsu:
17366 case Intrinsic::arm_neon_vqshiftns:
17367 case Intrinsic::arm_neon_vqshiftnu:
17368 case Intrinsic::arm_neon_vqshiftnsu:
17369 case Intrinsic::arm_neon_vqrshiftns:
17370 case Intrinsic::arm_neon_vqrshiftnu:
17371 case Intrinsic::arm_neon_vqrshiftnsu: {
17372 EVT VT =
N->getOperand(1).getValueType();
17374 unsigned VShiftOpc = 0;
17377 case Intrinsic::arm_neon_vshifts:
17378 case Intrinsic::arm_neon_vshiftu:
17380 VShiftOpc = ARMISD::VSHLIMM;
17383 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17384 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17385 : ARMISD::VSHRuIMM);
17390 case Intrinsic::arm_neon_vrshifts:
17391 case Intrinsic::arm_neon_vrshiftu:
17396 case Intrinsic::arm_neon_vqshifts:
17397 case Intrinsic::arm_neon_vqshiftu:
17402 case Intrinsic::arm_neon_vqshiftsu:
17407 case Intrinsic::arm_neon_vrshiftn:
17408 case Intrinsic::arm_neon_vqshiftns:
17409 case Intrinsic::arm_neon_vqshiftnu:
17410 case Intrinsic::arm_neon_vqshiftnsu:
17411 case Intrinsic::arm_neon_vqrshiftns:
17412 case Intrinsic::arm_neon_vqrshiftnu:
17413 case Intrinsic::arm_neon_vqrshiftnsu:
17425 case Intrinsic::arm_neon_vshifts:
17426 case Intrinsic::arm_neon_vshiftu:
17429 case Intrinsic::arm_neon_vrshifts:
17430 VShiftOpc = ARMISD::VRSHRsIMM;
17432 case Intrinsic::arm_neon_vrshiftu:
17433 VShiftOpc = ARMISD::VRSHRuIMM;
17435 case Intrinsic::arm_neon_vrshiftn:
17436 VShiftOpc = ARMISD::VRSHRNIMM;
17438 case Intrinsic::arm_neon_vqshifts:
17439 VShiftOpc = ARMISD::VQSHLsIMM;
17441 case Intrinsic::arm_neon_vqshiftu:
17442 VShiftOpc = ARMISD::VQSHLuIMM;
17444 case Intrinsic::arm_neon_vqshiftsu:
17445 VShiftOpc = ARMISD::VQSHLsuIMM;
17447 case Intrinsic::arm_neon_vqshiftns:
17448 VShiftOpc = ARMISD::VQSHRNsIMM;
17450 case Intrinsic::arm_neon_vqshiftnu:
17451 VShiftOpc = ARMISD::VQSHRNuIMM;
17453 case Intrinsic::arm_neon_vqshiftnsu:
17454 VShiftOpc = ARMISD::VQSHRNsuIMM;
17456 case Intrinsic::arm_neon_vqrshiftns:
17457 VShiftOpc = ARMISD::VQRSHRNsIMM;
17459 case Intrinsic::arm_neon_vqrshiftnu:
17460 VShiftOpc = ARMISD::VQRSHRNuIMM;
17462 case Intrinsic::arm_neon_vqrshiftnsu:
17463 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17468 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17469 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17472 case Intrinsic::arm_neon_vshiftins: {
17473 EVT VT =
N->getOperand(1).getValueType();
17475 unsigned VShiftOpc = 0;
17478 VShiftOpc = ARMISD::VSLIIMM;
17479 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17480 VShiftOpc = ARMISD::VSRIIMM;
17486 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17487 N->getOperand(1),
N->getOperand(2),
17491 case Intrinsic::arm_neon_vqrshifts:
17492 case Intrinsic::arm_neon_vqrshiftu:
17496 case Intrinsic::arm_neon_vbsl: {
17498 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17499 N->getOperand(2),
N->getOperand(3));
17501 case Intrinsic::arm_mve_vqdmlah:
17502 case Intrinsic::arm_mve_vqdmlash:
17503 case Intrinsic::arm_mve_vqrdmlah:
17504 case Intrinsic::arm_mve_vqrdmlash:
17505 case Intrinsic::arm_mve_vmla_n_predicated:
17506 case Intrinsic::arm_mve_vmlas_n_predicated:
17507 case Intrinsic::arm_mve_vqdmlah_predicated:
17508 case Intrinsic::arm_mve_vqdmlash_predicated:
17509 case Intrinsic::arm_mve_vqrdmlah_predicated:
17510 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17515 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17522 case Intrinsic::arm_mve_minv:
17523 case Intrinsic::arm_mve_maxv:
17524 case Intrinsic::arm_mve_minav:
17525 case Intrinsic::arm_mve_maxav:
17526 case Intrinsic::arm_mve_minv_predicated:
17527 case Intrinsic::arm_mve_maxv_predicated:
17528 case Intrinsic::arm_mve_minav_predicated:
17529 case Intrinsic::arm_mve_maxav_predicated: {
17532 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17539 case Intrinsic::arm_mve_addv: {
17542 bool Unsigned =
N->getConstantOperandVal(2);
17543 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17547 case Intrinsic::arm_mve_addlv:
17548 case Intrinsic::arm_mve_addlv_predicated: {
17551 bool Unsigned =
N->getConstantOperandVal(2);
17552 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17553 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17554 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17557 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17559 Ops.push_back(
N->getOperand(i));
17580 EVT VT =
N->getValueType(0);
17582 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17583 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17584 N->getOperand(0)->hasOneUse()) {
17601 if (AndMask == 255 || AndMask == 65535)
17605 if (MaskedBits > ShiftAmt) {
17620 if (ST->hasMVEIntegerOps())
17625 switch (
N->getOpcode()) {
17631 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17638 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17639 unsigned VShiftOpc =
17640 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17642 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17658 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17661 EVT FromVT = LD->getValueType(0);
17662 EVT ToVT =
N->getValueType(0);
17669 unsigned NumElements = 0;
17670 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17672 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17674 if (NumElements == 0 ||
17684 SDValue BasePtr = LD->getBasePtr();
17685 Align Alignment = LD->getBaseAlign();
17706 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17707 Alignment, MMOFlags, AAInfo);
17713 if (FromEltVT == MVT::f16) {
17716 for (
unsigned i = 0; i < Loads.
size(); i++) {
17718 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
17742 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17746 EVT VT =
N->getValueType(0);
17750 if (VT == MVT::i32 &&
17751 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17756 switch (
N->getOpcode()) {
17759 Opc = ARMISD::VGETLANEs;
17763 Opc = ARMISD::VGETLANEu;
17770 if (ST->hasMVEIntegerOps())
17779 if (ST->hasMVEFloatOps())
17790 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17794 EVT VT =
Op.getValueType();
17797 if (VT != MVT::i32 ||
17810 APInt MaxC = Max.getConstantOperandAPInt(1);
17813 !(MinC + 1).isPowerOf2())
17831 EVT VT =
N->getValueType(0);
17834 if (VT == MVT::i32)
17837 if (!ST->hasMVEIntegerOps())
17843 if (VT != MVT::v4i32 && VT != MVT::v8i16)
17846 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
17854 if (VT == MVT::v4i32)
17855 SaturateC =
APInt(32, (1 << 15) - 1,
true);
17857 SaturateC =
APInt(16, (1 << 7) - 1,
true);
17864 MaxC != ~SaturateC)
17869 if (IsSignedSaturate(
N, N0.
getNode())) {
17872 if (VT == MVT::v4i32) {
17873 HalfVT = MVT::v8i16;
17874 ExtVT = MVT::v4i16;
17876 HalfVT = MVT::v16i8;
17891 auto IsUnsignedSaturate = [&](
SDNode *Min) {
17897 if (VT == MVT::v4i32)
17898 SaturateC =
APInt(32, (1 << 16) - 1,
true);
17900 SaturateC =
APInt(16, (1 << 8) - 1,
true);
17909 if (IsUnsignedSaturate(
N)) {
17913 if (VT == MVT::v4i32) {
17914 HalfVT = MVT::v8i16;
17915 ExtConst = 0x0000FFFF;
17917 HalfVT = MVT::v16i8;
17939 const APInt *CV = &
C->getAPIntValue();
17957 SDValue Op0 = CMOV->getOperand(0);
17958 SDValue Op1 = CMOV->getOperand(1);
17959 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
17960 SDValue CmpZ = CMOV->getOperand(3);
17996 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18003 if ((OrCI & Known.
Zero) != OrCI)
18009 EVT VT =
X.getValueType();
18010 unsigned BitInX = AndC->
logBase2();
18018 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18019 BitInY < NumActiveBits; ++BitInY) {
18020 if (OrCI[BitInY] == 0)
18023 Mask.setBit(BitInY);
18024 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18040 switch (
N->getOpcode()) {
18055 if (Const->isZero())
18057 else if (Const->isOne())
18065 unsigned IntOp =
N.getConstantOperandVal(1);
18066 if (IntOp != Intrinsic::test_start_loop_iterations &&
18067 IntOp != Intrinsic::loop_decrement_reg)
18093 bool Negate =
false;
18097 if (
N->getOpcode() == ISD::BRCOND) {
18099 Cond =
N->getOperand(1);
18100 Dest =
N->getOperand(2);
18102 assert(
N->getOpcode() == ISD::BR_CC &&
"Expected BRCOND or BR_CC!");
18104 Cond =
N->getOperand(2);
18105 Dest =
N->getOperand(4);
18107 if (!Const->isOne() && !Const->isZero())
18109 Imm = Const->getZExtValue();
18137 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18138 "unsupported condition");
18143 unsigned IntOp =
Int->getConstantOperandVal(1);
18144 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() == ISD::BR) &&
18145 "expected single br user");
18146 SDNode *Br = *
N->user_begin();
18156 if (IntOp == Intrinsic::test_start_loop_iterations) {
18158 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18160 if (IsTrueIfZero(CC, Imm)) {
18162 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18166 UpdateUncondBr(Br, Dest, DAG);
18168 SDValue Ops[] = {Chain, Setup, OtherTarget};
18169 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18181 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18185 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18189 if (
Target == OtherTarget)
18190 UpdateUncondBr(Br, Dest, DAG);
18196 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18205 if (Cmp.getOpcode() != ARMISD::CMPZ)
18210 SDValue LHS = Cmp.getOperand(0);
18211 SDValue RHS = Cmp.getOperand(1);
18220 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18221 LHS->getOperand(0)->hasOneUse() &&
18225 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18237 if (Cmp.getOpcode() != ARMISD::CMPZ)
18241 EVT VT =
N->getValueType(0);
18243 SDValue LHS = Cmp.getOperand(0);
18244 SDValue RHS = Cmp.getOperand(1);
18245 SDValue FalseVal =
N->getOperand(0);
18246 SDValue TrueVal =
N->getOperand(1);
18251 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18275 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18276 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18277 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18280 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18285 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18288 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18289 LHS->getOperand(2), LHS->getOperand(3));
18299 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18303 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18305 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18314 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18347 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18359 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18379 const APInt *TrueConst;
18380 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18381 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18382 FalseVal.getOperand(1) == RHS) ||
18386 unsigned ShiftAmount = TrueConst->
logBase2();
18401 if (Known.
Zero == 0xfffffffe)
18404 else if (Known.
Zero == 0xffffff00)
18407 else if (Known.
Zero == 0xffff0000)
18420 EVT DstVT =
N->getValueType(0);
18423 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18424 EVT SrcVT = Src.getValueType();
18426 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18431 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18432 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18433 Src.getValueType().getScalarSizeInBits())
18434 Src = Src.getOperand(0);
18438 EVT SrcVT = Src.getValueType();
18439 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18440 Src.getOpcode() == ARMISD::VMVNIMM ||
18441 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18444 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18458 EVT VT =
N->getValueType(0);
18466 if (
N->getNumOperands() == 2 &&
18470 N->getOperand(0).getOperand(1),
18471 N->getOperand(1).getOperand(0),
18472 N->getOperand(1).getOperand(1));
18475 if (
N->getNumOperands() == 2 &&
18481 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18482 S0->getOperand(1) ==
S1->getOperand(1)) {
18485 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18489 ARMISD::VMOVN,
DL, VT,
18490 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18491 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18495 ARMISD::VMOVN,
DL, VT,
18496 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18497 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18505 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18506 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18507 (Op.getOpcode() == ISD::BITCAST &&
18508 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18511 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18513 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18531 int NumIns =
N->getNumOperands();
18532 assert((NumIns == 2 || NumIns == 4) &&
18533 "Expected 2 or 4 inputs to an MVETrunc");
18535 if (
N->getNumOperands() == 4)
18539 for (
int I = 0;
I < NumIns;
I++) {
18541 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18546 Ptr, MPI, StoreVT,
Align(4));
18561 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18564 EVT FromVT = LD->getMemoryVT();
18565 EVT ToVT =
N->getValueType(0);
18572 unsigned NumElements = 0;
18573 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18575 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18577 assert(NumElements != 0);
18583 LD->getExtensionType() != NewExtType)
18590 SDValue BasePtr = LD->getBasePtr();
18591 Align Alignment = LD->getBaseAlign();
18610 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18611 Alignment, MMOFlags, AAInfo);
18627 EVT VT =
N->getValueType(0);
18629 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18630 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18632 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18634 auto Extend = [&](
SDValue V) {
18643 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
18644 SDValue Ext = Extend(
N->getOperand(0));
18652 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18653 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
18657 auto CheckInregMask = [&](
int Start,
int Offset) {
18659 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18665 if (CheckInregMask(0, 0))
18667 else if (CheckInregMask(0, 1))
18668 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18669 else if (CheckInregMask(0, Mask.size()))
18671 else if (CheckInregMask(0, Mask.size() + 1))
18672 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18677 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18681 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18688 if (
N->getOperand(0)->getOpcode() == ISD::LOAD)
18699 int NumOuts =
N->getNumValues();
18700 assert((NumOuts == 2 || NumOuts == 4) &&
18701 "Expected 2 or 4 outputs to an MVEEXT");
18702 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18704 if (
N->getNumOperands() == 4)
18710 StackPtr, MPI,
Align(4));
18713 for (
int I = 0;
I < NumOuts;
I++) {
18715 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18716 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18721 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
18730 switch (
N->getOpcode()) {
18781 case ISD::FP_EXTEND:
18790 case ARMISD::BRCOND:
18794 case ARMISD::CSINC:
18795 case ARMISD::CSINV:
18796 case ARMISD::CSNEG:
18809 case ARMISD::PREDICATE_CAST:
18811 case ARMISD::VECTOR_REG_CAST:
18820 case ISD::VECREDUCE_ADD:
18822 case ARMISD::VADDVs:
18823 case ARMISD::VADDVu:
18824 case ARMISD::VADDLVs:
18825 case ARMISD::VADDLVu:
18826 case ARMISD::VADDLVAs:
18827 case ARMISD::VADDLVAu:
18828 case ARMISD::VMLAVs:
18829 case ARMISD::VMLAVu:
18830 case ARMISD::VMLALVs:
18831 case ARMISD::VMLALVu:
18832 case ARMISD::VMLALVAs:
18833 case ARMISD::VMLALVAu:
18835 case ARMISD::VMOVN:
18837 case ARMISD::VQMOVNs:
18838 case ARMISD::VQMOVNu:
18840 case ARMISD::VQDMULH:
18846 case ARMISD::SMULWB: {
18847 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18853 case ARMISD::SMULWT: {
18854 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18860 case ARMISD::SMLALBB:
18861 case ARMISD::QADD16b:
18862 case ARMISD::QSUB16b:
18863 case ARMISD::UQADD16b:
18864 case ARMISD::UQSUB16b: {
18865 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18872 case ARMISD::SMLALBT: {
18873 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
18875 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
18882 case ARMISD::SMLALTB: {
18883 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
18885 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
18892 case ARMISD::SMLALTT: {
18893 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18900 case ARMISD::QADD8b:
18901 case ARMISD::QSUB8b:
18902 case ARMISD::UQADD8b:
18903 case ARMISD::UQSUB8b: {
18904 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18912 if (
N->getOperand(1) ==
N->getOperand(2))
18913 return N->getOperand(1);
18917 switch (
N->getConstantOperandVal(1)) {
18918 case Intrinsic::arm_neon_vld1:
18919 case Intrinsic::arm_neon_vld1x2:
18920 case Intrinsic::arm_neon_vld1x3:
18921 case Intrinsic::arm_neon_vld1x4:
18922 case Intrinsic::arm_neon_vld2:
18923 case Intrinsic::arm_neon_vld3:
18924 case Intrinsic::arm_neon_vld4:
18925 case Intrinsic::arm_neon_vld2lane:
18926 case Intrinsic::arm_neon_vld3lane:
18927 case Intrinsic::arm_neon_vld4lane:
18928 case Intrinsic::arm_neon_vld2dup:
18929 case Intrinsic::arm_neon_vld3dup:
18930 case Intrinsic::arm_neon_vld4dup:
18931 case Intrinsic::arm_neon_vst1:
18932 case Intrinsic::arm_neon_vst1x2:
18933 case Intrinsic::arm_neon_vst1x3:
18934 case Intrinsic::arm_neon_vst1x4:
18935 case Intrinsic::arm_neon_vst2:
18936 case Intrinsic::arm_neon_vst3:
18937 case Intrinsic::arm_neon_vst4:
18938 case Intrinsic::arm_neon_vst2lane:
18939 case Intrinsic::arm_neon_vst3lane:
18940 case Intrinsic::arm_neon_vst4lane:
18942 case Intrinsic::arm_mve_vld2q:
18943 case Intrinsic::arm_mve_vld4q:
18944 case Intrinsic::arm_mve_vst2q:
18945 case Intrinsic::arm_mve_vst4q:
18956 return (VT == MVT::f32) && (
Opc == ISD::LOAD ||
Opc == ISD::STORE);
18962 unsigned *
Fast)
const {
18968 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
18971 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
18973 if (AllowsUnaligned) {
18975 *
Fast = Subtarget->hasV7Ops();
18980 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
18984 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
18991 if (!Subtarget->hasMVEIntegerOps())
18995 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
18996 Ty == MVT::v2i1)) {
19004 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19020 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19021 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19022 Ty == MVT::v2f64) {
19033 const AttributeList &FuncAttributes)
const {
19035 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19036 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19038 if (
Op.size() >= 16 &&
19044 }
else if (
Op.size() >= 8 &&
19061 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19063 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19065 return (SrcBits == 64 && DestBits == 32);
19074 return (SrcBits == 64 && DestBits == 32);
19110 return Subtarget->hasFullFP16();
19117 if (!Subtarget->hasMVEIntegerOps())
19136 if (Ld->isExpandingLoad())
19140 if (Subtarget->hasMVEIntegerOps())
19153 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19185bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19187 if (Subtarget->useSoftFloat())
19196 return Subtarget->hasMVEFloatOps();
19214 unsigned Scale = 1;
19231 if ((V & (Scale - 1)) != 0)
19240 if (VT.
isVector() && Subtarget->hasNEON())
19243 !Subtarget->hasMVEFloatOps())
19246 bool IsNeg =
false;
19252 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19255 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19271 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19277 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19307 default:
return false;
19326 int Scale = AM.
Scale;
19331 default:
return false;
19339 Scale = Scale & ~1;
19340 return Scale == 2 || Scale == 4 || Scale == 8;
19357 if (Scale & 1)
return false;
19364 const int Scale = AM.
Scale;
19374 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19390 switch (AM.
Scale) {
19401 if (Subtarget->isThumb1Only())
19404 if (Subtarget->isThumb2())
19407 int Scale = AM.
Scale;
19409 default:
return false;
19413 if (Scale < 0) Scale = -Scale;
19421 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19434 if (Scale & 1)
return false;
19447 if (!Subtarget->isThumb())
19450 if (Subtarget->isThumb2())
19454 return Imm >= 0 && Imm <= 255;
19464 if (!Subtarget->isThumb())
19466 if (Subtarget->isThumb2())
19469 return AbsImm <= 255;
19504 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19508 int RHSC = (int)
RHS->getZExtValue();
19509 if (RHSC < 0 && RHSC > -256) {
19519 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19522 int RHSC = (int)
RHS->getZExtValue();
19523 if (RHSC < 0 && RHSC > -0x1000) {
19565 int RHSC = (int)
RHS->getZExtValue();
19566 if (RHSC < 0 && RHSC > -0x100) {
19571 }
else if (RHSC > 0 && RHSC < 0x100) {
19582 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19593 bool CanChangeType = isLE && !IsMasked;
19596 int RHSC = (int)
RHS->getZExtValue();
19598 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19599 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19604 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19615 if (VT == MVT::v4i16) {
19616 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19618 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19619 if (IsInRange(RHSC, 0x80, 1))
19621 }
else if (Alignment >= 4 &&
19622 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19623 IsInRange(RHSC, 0x80, 4))
19625 else if (Alignment >= 2 &&
19626 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19627 IsInRange(RHSC, 0x80, 2))
19629 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19642 if (Subtarget->isThumb1Only())
19648 bool isSEXTLoad =
false;
19649 bool IsMasked =
false;
19651 Ptr = LD->getBasePtr();
19652 VT = LD->getMemoryVT();
19653 Alignment = LD->getAlign();
19656 Ptr = ST->getBasePtr();
19657 VT = ST->getMemoryVT();
19658 Alignment = ST->getAlign();
19660 Ptr = LD->getBasePtr();
19661 VT = LD->getMemoryVT();
19662 Alignment = LD->getAlign();
19666 Ptr = ST->getBasePtr();
19667 VT = ST->getMemoryVT();
19668 Alignment = ST->getAlign();
19674 bool isLegal =
false;
19676 isLegal = Subtarget->hasMVEIntegerOps() &&
19678 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19679 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19681 if (Subtarget->isThumb2())
19706 bool isSEXTLoad =
false, isNonExt;
19707 bool IsMasked =
false;
19709 VT = LD->getMemoryVT();
19710 Ptr = LD->getBasePtr();
19711 Alignment = LD->getAlign();
19715 VT = ST->getMemoryVT();
19716 Ptr = ST->getBasePtr();
19717 Alignment = ST->getAlign();
19718 isNonExt = !ST->isTruncatingStore();
19720 VT = LD->getMemoryVT();
19721 Ptr = LD->getBasePtr();
19722 Alignment = LD->getAlign();
19727 VT = ST->getMemoryVT();
19728 Ptr = ST->getBasePtr();
19729 Alignment = ST->getAlign();
19730 isNonExt = !ST->isTruncatingStore();
19735 if (Subtarget->isThumb1Only()) {
19738 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19739 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19742 if (!RHS || RHS->getZExtValue() != 4)
19744 if (Alignment <
Align(4))
19748 Base =
Op->getOperand(0);
19754 bool isLegal =
false;
19756 isLegal = Subtarget->hasMVEIntegerOps() &&
19761 if (Subtarget->isThumb2())
19775 !Subtarget->isThumb2())
19789 const APInt &DemandedElts,
19791 unsigned Depth)
const {
19794 switch (
Op.getOpcode()) {
19801 if (
Op.getResNo() == 0) {
19812 case ARMISD::CMOV: {
19827 case Intrinsic::arm_ldaex:
19828 case Intrinsic::arm_ldrex: {
19836 case ARMISD::BFI: {
19843 const APInt &Mask =
Op.getConstantOperandAPInt(2);
19844 Known.
Zero &= Mask;
19848 case ARMISD::VGETLANEs:
19849 case ARMISD::VGETLANEu: {
19850 const SDValue &SrcSV =
Op.getOperand(0);
19856 "VGETLANE index out of bounds");
19861 EVT VT =
Op.getValueType();
19867 if (
Op.getOpcode() == ARMISD::VGETLANEs)
19868 Known = Known.
sext(DstSz);
19870 Known = Known.
zext(DstSz);
19875 case ARMISD::VMOVrh: {
19878 Known = KnownOp.
zext(32);
19881 case ARMISD::CSINC:
19882 case ARMISD::CSINV:
19883 case ARMISD::CSNEG: {
19891 if (
Op.getOpcode() == ARMISD::CSINC)
19894 else if (
Op.getOpcode() == ARMISD::CSINV)
19896 else if (
Op.getOpcode() == ARMISD::CSNEG)
19903 case ARMISD::VORRIMM:
19904 case ARMISD::VBICIMM: {
19905 unsigned Encoded =
Op.getConstantOperandVal(1);
19906 unsigned DecEltBits = 0;
19909 unsigned EltBits =
Op.getScalarValueSizeInBits();
19910 if (EltBits != DecEltBits) {
19919 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
19920 APInt Imm(DecEltBits, DecodedVal);
19922 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
19923 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
19941 EVT VT =
Op.getValueType();
19947 assert(VT == MVT::i32 &&
"Unexpected integer type");
19954 unsigned Mask =
C->getZExtValue();
19957 unsigned ShrunkMask = Mask & Demanded;
19958 unsigned ExpandedMask = Mask | ~Demanded;
19962 if (ShrunkMask == 0)
19968 if (ExpandedMask == ~0U)
19971 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
19972 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
19974 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
19975 if (NewMask == Mask)
19984 if (IsLegalMask(0xFF))
19985 return UseMask(0xFF);
19988 if (IsLegalMask(0xFFFF))
19989 return UseMask(0xFFFF);
19993 if (ShrunkMask < 256)
19994 return UseMask(ShrunkMask);
19998 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
19999 return UseMask(ExpandedMask);
20014 unsigned Depth)
const {
20015 unsigned Opc =
Op.getOpcode();
20019 case ARMISD::LSRL: {
20023 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20025 unsigned ShAmt =
Op->getConstantOperandVal(2);
20035 case ARMISD::VBICIMM: {
20037 unsigned ModImm =
Op.getConstantOperandVal(1);
20038 unsigned EltBits = 0;
20040 if ((OriginalDemandedBits & Mask) == 0)
20046 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20061 if (!Subtarget->hasVFP2Base())
20065 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20077 unsigned S = Constraint.
size();
20079 switch (Constraint[0]) {
20091 }
else if (S == 2) {
20092 switch (Constraint[0]) {
20109 Value *CallOperandVal =
info.CallOperandVal;
20112 if (!CallOperandVal)
20116 switch (*constraint) {
20122 if (Subtarget->isThumb())
20137 if (PR == 0 || VT == MVT::Other)
20139 if (ARM::SPRRegClass.
contains(PR))
20140 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20141 if (ARM::DPRRegClass.
contains(PR))
20146using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20150 switch (Constraint.
size()) {
20153 switch (Constraint[0]) {
20155 if (Subtarget->isThumb())
20156 return RCPair(0U, &ARM::tGPRRegClass);
20157 return RCPair(0U, &ARM::GPRRegClass);
20159 if (Subtarget->isThumb())
20160 return RCPair(0U, &ARM::hGPRRegClass);
20163 if (Subtarget->isThumb1Only())
20164 return RCPair(0U, &ARM::tGPRRegClass);
20165 return RCPair(0U, &ARM::GPRRegClass);
20167 if (VT == MVT::Other)
20169 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20170 return RCPair(0U, &ARM::SPRRegClass);
20172 return RCPair(0U, &ARM::DPRRegClass);
20174 return RCPair(0U, &ARM::QPRRegClass);
20177 if (VT == MVT::Other)
20179 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20180 return RCPair(0U, &ARM::SPR_8RegClass);
20182 return RCPair(0U, &ARM::DPR_8RegClass);
20184 return RCPair(0U, &ARM::QPR_8RegClass);
20187 if (VT == MVT::Other)
20189 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20190 return RCPair(0U, &ARM::SPRRegClass);
20192 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20194 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20200 if (Constraint[0] ==
'T') {
20201 switch (Constraint[1]) {
20205 return RCPair(0U, &ARM::tGPREvenRegClass);
20207 return RCPair(0U, &ARM::tGPROddRegClass);
20216 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20217 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20221 return {0,
nullptr};
20229 std::vector<SDValue> &
Ops,
20234 if (Constraint.
size() != 1)
20237 char ConstraintLetter = Constraint[0];
20238 switch (ConstraintLetter) {
20241 case 'I':
case 'J':
case 'K':
case 'L':
20242 case 'M':
case 'N':
case 'O':
20247 int64_t CVal64 =
C->getSExtValue();
20248 int CVal = (int) CVal64;
20251 if (CVal != CVal64)
20254 switch (ConstraintLetter) {
20258 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20259 if (CVal >= 0 && CVal <= 65535)
20263 if (Subtarget->isThumb1Only()) {
20266 if (CVal >= 0 && CVal <= 255)
20268 }
else if (Subtarget->isThumb2()) {
20282 if (Subtarget->isThumb1Only()) {
20287 if (CVal >= -255 && CVal <= -1)
20293 if (CVal >= -4095 && CVal <= 4095)
20299 if (Subtarget->isThumb1Only()) {
20306 }
else if (Subtarget->isThumb2()) {
20326 if (Subtarget->isThumb1Only()) {
20329 if (CVal >= -7 && CVal < 7)
20331 }
else if (Subtarget->isThumb2()) {
20351 if (Subtarget->isThumb1Only()) {
20354 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20360 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20366 if (Subtarget->isThumb1Only()) {
20368 if (CVal >= 0 && CVal <= 31)
20374 if (Subtarget->isThumb1Only()) {
20377 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20386 if (Result.getNode()) {
20387 Ops.push_back(Result);
20397 "Unhandled Opcode in getDivRemLibcall");
20403 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20404 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20405 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20406 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20415 "Unhandled Opcode in getDivRemArgList");
20419 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20420 EVT ArgVT =
N->getOperand(i).getValueType();
20425 Args.push_back(Entry);
20433 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20434 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20435 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20436 "Register-based DivRem lowering only");
20437 unsigned Opcode =
Op->getOpcode();
20439 "Invalid opcode for Div/Rem lowering");
20441 EVT VT =
Op->getValueType(0);
20463 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20464 : Subtarget->hasDivideInARMMode();
20465 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20466 Op->getSimpleValueType(0) == MVT::i32) {
20468 const SDValue Dividend =
Op->getOperand(0);
20469 const SDValue Divisor =
Op->getOperand(1);
20470 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20474 SDValue Values[2] = {Div, Rem};
20491 if (Subtarget->isTargetWindows())
20494 TargetLowering::CallLoweringInfo CLI(DAG);
20499 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20500 return CallInfo.first;
20506 EVT VT =
N->getValueType(0);
20512 Result[0], Result[1]);
20516 std::vector<Type*> RetTyParams;
20517 Type *RetTyElement;
20527 RetTyParams.push_back(RetTyElement);
20528 RetTyParams.push_back(RetTyElement);
20541 if (Subtarget->isTargetWindows())
20549 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20552 SDNode *ResNode = CallResult.first.getNode();
20559 assert(Subtarget->isTargetWindows() &&
"unsupported target platform");
20567 "no-stack-arg-probe")) {
20571 Chain =
SP.getValue(1);
20588 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20589 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
20599 bool IsStrict =
Op->isStrictFPOpcode();
20600 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20601 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20603 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20604 "Unexpected type for custom-lowering FP_EXTEND");
20606 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20607 "With both FP DP and 16, any FP conversion is legal!");
20609 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20610 "With FP16, 16 to 32 conversion is legal!");
20613 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20618 Loc,
Op.getValueType(), SrcVal);
20633 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20634 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20635 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20636 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20640 {DstVT, MVT::Other}, {Chain, SrcVal});
20643 SrcVal = DAG.
getNode(ISD::FP_EXTEND, Loc, DstVT, SrcVal);
20647 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20648 "Unexpected type for custom-lowering FP_EXTEND");
20649 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20654 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20658 bool IsStrict =
Op->isStrictFPOpcode();
20660 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20662 EVT DstVT =
Op.getValueType();
20663 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20666 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20667 "Unexpected type for custom-lowering FP_ROUND");
20669 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20670 "With both FP DP and 16, any FP conversion is legal!");
20675 if (SrcSz == 32 && Subtarget->hasFP16())
20680 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20681 "Unexpected type for custom-lowering FP_ROUND");
20685 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20697 if (v == 0xffffffff)
20709 bool ForCodeSize)
const {
20710 if (!Subtarget->hasVFP3Base())
20712 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20714 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20717 if (VT == MVT::f32)
20719 if (VT == MVT::f64 && Subtarget->hasFP64())
20732 case Intrinsic::arm_neon_vld1:
20733 case Intrinsic::arm_neon_vld2:
20734 case Intrinsic::arm_neon_vld3:
20735 case Intrinsic::arm_neon_vld4:
20736 case Intrinsic::arm_neon_vld2lane:
20737 case Intrinsic::arm_neon_vld3lane:
20738 case Intrinsic::arm_neon_vld4lane:
20739 case Intrinsic::arm_neon_vld2dup:
20740 case Intrinsic::arm_neon_vld3dup:
20741 case Intrinsic::arm_neon_vld4dup: {
20744 auto &
DL =
I.getDataLayout();
20745 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20747 Info.ptrVal =
I.getArgOperand(0);
20749 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20755 case Intrinsic::arm_neon_vld1x2:
20756 case Intrinsic::arm_neon_vld1x3:
20757 case Intrinsic::arm_neon_vld1x4: {
20760 auto &
DL =
I.getDataLayout();
20761 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20763 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20765 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20770 case Intrinsic::arm_neon_vst1:
20771 case Intrinsic::arm_neon_vst2:
20772 case Intrinsic::arm_neon_vst3:
20773 case Intrinsic::arm_neon_vst4:
20774 case Intrinsic::arm_neon_vst2lane:
20775 case Intrinsic::arm_neon_vst3lane:
20776 case Intrinsic::arm_neon_vst4lane: {
20779 auto &
DL =
I.getDataLayout();
20780 unsigned NumElts = 0;
20781 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20782 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20785 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20788 Info.ptrVal =
I.getArgOperand(0);
20790 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20796 case Intrinsic::arm_neon_vst1x2:
20797 case Intrinsic::arm_neon_vst1x3:
20798 case Intrinsic::arm_neon_vst1x4: {
20801 auto &
DL =
I.getDataLayout();
20802 unsigned NumElts = 0;
20803 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20804 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20807 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20810 Info.ptrVal =
I.getArgOperand(0);
20812 Info.align =
I.getParamAlign(0).valueOrOne();
20817 case Intrinsic::arm_mve_vld2q:
20818 case Intrinsic::arm_mve_vld4q: {
20822 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
20824 Info.ptrVal =
I.getArgOperand(0);
20831 case Intrinsic::arm_mve_vst2q:
20832 case Intrinsic::arm_mve_vst4q: {
20835 Type *VecTy =
I.getArgOperand(1)->getType();
20836 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
20838 Info.ptrVal =
I.getArgOperand(0);
20845 case Intrinsic::arm_mve_vldr_gather_base:
20846 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
20848 Info.ptrVal =
nullptr;
20850 Info.align =
Align(1);
20854 case Intrinsic::arm_mve_vldr_gather_base_wb:
20855 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
20857 Info.ptrVal =
nullptr;
20858 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
20859 Info.align =
Align(1);
20863 case Intrinsic::arm_mve_vldr_gather_offset:
20864 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
20866 Info.ptrVal =
nullptr;
20871 Info.align =
Align(1);
20875 case Intrinsic::arm_mve_vstr_scatter_base:
20876 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
20878 Info.ptrVal =
nullptr;
20879 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
20880 Info.align =
Align(1);
20884 case Intrinsic::arm_mve_vstr_scatter_base_wb:
20885 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
20887 Info.ptrVal =
nullptr;
20888 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
20889 Info.align =
Align(1);
20893 case Intrinsic::arm_mve_vstr_scatter_offset:
20894 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
20896 Info.ptrVal =
nullptr;
20901 Info.align =
Align(1);
20905 case Intrinsic::arm_ldaex:
20906 case Intrinsic::arm_ldrex: {
20907 auto &
DL =
I.getDataLayout();
20908 Type *ValTy =
I.getParamElementType(0);
20911 Info.ptrVal =
I.getArgOperand(0);
20913 Info.align =
DL.getABITypeAlign(ValTy);
20917 case Intrinsic::arm_stlex:
20918 case Intrinsic::arm_strex: {
20919 auto &
DL =
I.getDataLayout();
20920 Type *ValTy =
I.getParamElementType(1);
20923 Info.ptrVal =
I.getArgOperand(1);
20925 Info.align =
DL.getABITypeAlign(ValTy);
20929 case Intrinsic::arm_stlexd:
20930 case Intrinsic::arm_strexd:
20932 Info.memVT = MVT::i64;
20933 Info.ptrVal =
I.getArgOperand(2);
20935 Info.align =
Align(8);
20939 case Intrinsic::arm_ldaexd:
20940 case Intrinsic::arm_ldrexd:
20942 Info.memVT = MVT::i64;
20943 Info.ptrVal =
I.getArgOperand(0);
20945 Info.align =
Align(8);
20960 assert(Ty->isIntegerTy());
20962 unsigned Bits = Ty->getPrimitiveSizeInBits();
20963 if (Bits == 0 || Bits > 32)
20969 unsigned Index)
const {
20979 if (!Subtarget->hasDataBarrier()) {
20983 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
20984 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
20985 Builder.getInt32(0), Builder.getInt32(7),
20986 Builder.getInt32(10), Builder.getInt32(5)};
20987 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
20997 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
21018 if (Subtarget->preferISHSTBarriers())
21051 bool has64BitAtomicStore;
21052 if (Subtarget->isMClass())
21053 has64BitAtomicStore =
false;
21054 else if (Subtarget->isThumb())
21055 has64BitAtomicStore = Subtarget->hasV7Ops();
21057 has64BitAtomicStore = Subtarget->hasV6Ops();
21059 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21073 bool has64BitAtomicLoad;
21074 if (Subtarget->isMClass())
21075 has64BitAtomicLoad =
false;
21076 else if (Subtarget->isThumb())
21077 has64BitAtomicLoad = Subtarget->hasV7Ops();
21079 has64BitAtomicLoad = Subtarget->hasV6Ops();
21095 if (Subtarget->isMClass())
21096 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21097 else if (Subtarget->isThumb())
21098 hasAtomicRMW = Subtarget->hasV7Ops();
21100 hasAtomicRMW = Subtarget->hasV6Ops();
21101 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21124 bool HasAtomicCmpXchg;
21125 if (Subtarget->isMClass())
21126 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21127 else if (Subtarget->isThumb())
21128 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21130 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21132 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21139 return InsertFencesForAtomic;
21144 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21149 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21152 RTLIB::LibcallImpl SecurityCookieVar =
21154 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21155 SecurityCookieVar != RTLIB::Unsupported) {
21166 F->addParamAttr(0, Attribute::AttrKind::InReg);
21173 unsigned &
Cost)
const {
21175 if (!Subtarget->hasNEON())
21204 unsigned Opcode =
Op.getOpcode();
21206 case ARMISD::VORRIMM:
21207 case ARMISD::VBICIMM:
21215 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21219 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21224 if (!Subtarget->hasV7Ops())
21230 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21232 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21240 if (Subtarget->hasMinSize() && !Subtarget->isTargetWindows())
21249 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21255 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21257 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21260 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21262 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21263 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21264 if (!Subtarget->isLittle())
21266 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21267 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21268 return Builder.CreateOr(
21269 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21273 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21274 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21277 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21278 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21283 if (!Subtarget->hasV7Ops())
21285 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21291 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21299 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21303 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21304 if (!Subtarget->isLittle())
21306 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21309 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21313 CallInst *CI = Builder.CreateCall(
21314 Strex, {Builder.CreateZExtOrBitCast(
21324 return Subtarget->isMClass();
21332 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21339 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21342 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21350 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21358 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21361 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21366 if (Subtarget->hasNEON() && VecSize == 64)
21368 return VecSize % 128 == 0;
21372 if (Subtarget->hasNEON())
21374 if (Subtarget->hasMVEIntegerOps())
21394 "Invalid interleave factor");
21395 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21397 "Unmatched number of shufflevectors and indices");
21402 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21405 Type *EltTy = VecTy->getElementType();
21408 Align Alignment = LI->getAlign();
21426 Value *BaseAddr = LI->getPointerOperand();
21428 if (NumLoads > 1) {
21432 VecTy->getNumElements() / NumLoads);
21438 if (Subtarget->hasNEON()) {
21439 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21440 Type *Tys[] = {VecTy, PtrTy};
21441 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21442 Intrinsic::arm_neon_vld3,
21443 Intrinsic::arm_neon_vld4};
21446 Ops.push_back(BaseAddr);
21447 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21449 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21452 assert((Factor == 2 || Factor == 4) &&
21453 "expected interleave factor of 2 or 4 for MVE");
21455 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21456 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21457 Type *Tys[] = {VecTy, PtrTy};
21460 Ops.push_back(BaseAddr);
21461 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21471 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21475 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21476 VecTy->getNumElements() * Factor);
21482 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21484 unsigned Index = Indices[i];
21486 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21490 SubVec = Builder.CreateIntToPtr(
21494 SubVecs[SV].push_back(SubVec);
21503 auto &SubVec = SubVecs[SVI];
21506 SVI->replaceAllUsesWith(WideVec);
21542 const APInt &GapMask)
const {
21544 "Invalid interleave factor");
21549 "Unexpected mask on store");
21552 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21554 unsigned LaneLen = VecTy->getNumElements() / Factor;
21555 Type *EltTy = VecTy->getElementType();
21559 Align Alignment =
SI->getAlign();
21576 Type *IntTy =
DL.getIntPtrType(EltTy);
21581 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21582 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21588 Value *BaseAddr =
SI->getPointerOperand();
21590 if (NumStores > 1) {
21593 LaneLen /= NumStores;
21603 if (Subtarget->hasNEON()) {
21604 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21605 Intrinsic::arm_neon_vst3,
21606 Intrinsic::arm_neon_vst4};
21607 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21608 Type *Tys[] = {PtrTy, SubVecTy};
21611 Ops.push_back(BaseAddr);
21613 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21614 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21616 assert((Factor == 2 || Factor == 4) &&
21617 "expected interleave factor of 2 or 4 for MVE");
21619 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21620 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21621 Type *Tys[] = {PtrTy, SubVecTy};
21624 Ops.push_back(BaseAddr);
21626 for (
unsigned F = 0;
F < Factor;
F++) {
21627 Ops.push_back(Builder.getInt32(
F));
21628 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21634 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21637 if (StoreCount > 0)
21638 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21639 BaseAddr, LaneLen * Factor);
21644 for (
unsigned i = 0; i < Factor; i++) {
21645 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21646 if (Mask[IdxI] >= 0) {
21647 Shuffles.
push_back(Builder.CreateShuffleVector(
21650 unsigned StartMask = 0;
21651 for (
unsigned j = 1; j < LaneLen; j++) {
21652 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21653 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21654 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21664 Shuffles.
push_back(Builder.CreateShuffleVector(
21685 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21689 Members += SubMembers;
21695 Members += SubMembers * AT->getNumElements();
21696 }
else if (Ty->isFloatTy()) {
21701 }
else if (Ty->isDoubleTy()) {
21713 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21715 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21717 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21730 return (Members > 0 && Members <= 4);
21736 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21738 return ABITypeAlign;
21743 assert(StackAlign &&
"data layout string is missing stack alignment");
21744 return std::min(ABITypeAlign, *StackAlign);
21753 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21762 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
21763 return IsHA || IsIntArray;
21767 const Constant *PersonalityFn)
const {
21775 const Constant *PersonalityFn)
const {
21788void ARMTargetLowering::insertCopiesSplitCSR(
21792 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21802 RC = &ARM::GPRRegClass;
21803 else if (ARM::DPRRegClass.
contains(*
I))
21804 RC = &ARM::DPRRegClass;
21814 assert(Entry->getParent()->getFunction().hasFnAttribute(
21815 Attribute::NoUnwind) &&
21816 "Function should be nounwind in insertCopiesSplitCSR!");
21817 Entry->addLiveIn(*
I);
21822 for (
auto *Exit : Exits)
21824 TII->get(TargetOpcode::COPY), *
I)
21835 return Subtarget->hasMVEIntegerOps();
21845 unsigned NumElements = VTy->getNumElements();
21852 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
21853 return Subtarget->hasMVEFloatOps();
21858 return Subtarget->hasMVEIntegerOps() &&
21859 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
21860 ScalarTy->isIntegerTy(32));
21864 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
21875 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
21877 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
21879 if (TyWidth > 128) {
21880 int Stride = Ty->getNumElements() / 2;
21884 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
21886 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
21887 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
21888 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
21889 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
21890 Value *LowerSplitAcc =
nullptr;
21891 Value *UpperSplitAcc =
nullptr;
21894 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
21895 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
21899 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
21901 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
21903 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
21904 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
21911 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
21914 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
21916 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
21917 {ConstRotation, InputB, InputA});
21922 auto *ConstHalving = ConstantInt::get(IntTy, 1);
21925 ConstRotation = ConstantInt::get(IntTy, 0);
21927 ConstRotation = ConstantInt::get(IntTy, 1);
21929 if (!ConstRotation)
21932 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
21933 {ConstHalving, ConstRotation, InputA, InputB});
unsigned const MachineRegisterInfo * MRI
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool isNegatedInteger(SDValue Op)
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue LowerUADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue ConvertBooleanCarryToCarryFlag(SDValue BoolCarry, SelectionDAG &DAG)
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue ConvertCarryFlagToBooleanCarry(SDValue Flags, EVT VT, SelectionDAG &DAG)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static unsigned SelectPairHalf(unsigned Elements, ArrayRef< int > Mask, unsigned Index)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerTruncate(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformHWLoopCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, Value *Offset, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, Value *Offset, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned int Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static constexpr roundingMode rmTowardZero
LLVM_ABI bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
unsigned logBase2() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
const ARMBaseRegisterInfo & getRegisterInfo() const
const uint32_t * getSjLjDispatchPreservedMask(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const uint32_t * getTLSCallPreservedMask(const MachineFunction &MF) const
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
int getVarArgsFrameIndex() const
int getPromotedConstpoolIncrease() const
SmallPtrSet< const GlobalVariable *, 2 > & getGlobalsPromotedToConstantPool()
void setArgumentStackToRestore(unsigned v)
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
void setPromotedConstpoolIncrease(int Sz)
bool isThumb1OnlyFunction() const
void setArgRegsSaveSize(unsigned s)
bool isCmseNSEntryFunction() const
void setReturnRegsCount(unsigned s)
void setVarArgsFrameIndex(int Index)
unsigned getArgRegsSaveSize() const
void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV)
Indicate to the backend that GV has had its storage changed to inside a constant pool.
void setIsSplitCSR(bool s)
void setArgumentStackSize(unsigned size)
unsigned getArgumentStackSize() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
bool isTargetWindows() const
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
Align getDualLoadStoreAlignment() const
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool isReadOnly(const GlobalValue *GV) const
unsigned getMaxSupportedInterleaveFactor() const override
Get the maximum supported factor for interleaved memory accesses.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
unsigned getNumInterleavedAccesses(VectorType *VecTy, const DataLayout &DL) const
Returns the number of interleaved accesses that will be generated when lowering accesses of the given...
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Align getABIAlignmentForCallingConv(Type *ArgTy, const DataLayout &DL) const override
Return the correct alignment for the current calling convention.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void insertSSPDeclarations(Module &M) const override
Inserts necessary declarations for SSP (stack protection) purpose.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
bool shouldFoldConstantShiftPairToMask(const SDNode *N) const override
Return true if it is profitable to fold a pair of shifts into a mask.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override
Return true if it is profitable to combine an XOR of a logical shift to create a logical shift of NOT...
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const
PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
Value * createComplexDeinterleavingIR(IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, Value *Accumulator=nullptr) const override
Create the IR node for the given complex deinterleaving operation.
bool isComplexDeinterleavingSupported() const override
Does this target support complex deinterleaving.
SDValue PerformMVEExtCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &OriginalDemandedBits, const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the value type to use for ISD::SETCC.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const override
Perform a store-conditional operation to Addr.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool isVarArg) const
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for this result type with this index.
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
isShuffleMaskLegal - Targets can use this to indicate that they only support some VECTOR_SHUFFLE oper...
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
bool lowerInterleavedStore(Instruction *Store, Value *Mask, ShuffleVectorInst *SVI, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved store into a vstN intrinsic.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
bool useLoadStackGuardNode(const Module &M) const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vldN intrinsic.
std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override
Return the largest legal super-reg register class of the register class for the specified type and it...
bool preferSelectsOverBooleanArithmetic(EVT VT) const override
Should we prefer selects to doing arithmetic on boolean types.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
bool supportKCFIBundles() const override
Return true if the target supports kcfi operand bundles.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool isVarArg) const
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
allowsMisalignedMemoryAccesses - Returns true if the target allows unaligned memory accesses of the s...
bool isLegalInterleavedAccessType(unsigned Factor, FixedVectorType *VecTy, Align Alignment, const DataLayout &DL) const
Returns true if VecTy is a legal interleaved access type.
bool isVectorLoadExtDesirable(SDValue ExtVal) const override
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, unsigned &Cost) const override
Return true if the target can combine store(extractelement VectorTy,Idx).
bool useSoftFloat() const override
bool alignLoopsWithOptSize() const override
Should loops be aligned even when the function is marked OptSize (but not MinSize).
SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const
bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override
Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail ...
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
bool isFloatingPointOperation() const
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
The address of a basic block.
static BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
LLVM_ABI int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, uint32_t BitWidth) const
If this is a constant FP splat and the splatted constant FP is an exact power or 2,...
CCState - This class holds information needed while lowering arguments and return values.
void getInRegsParamInfo(unsigned InRegsParamRecordIndex, unsigned &BeginReg, unsigned &EndReg) const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
void rewindByValRegsInfo()
unsigned getInRegsParamsProcessed() const
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd)
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
unsigned getInRegsParamsCount() const
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
const APFloat & getValueAPF() const
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
MaybeAlign getStackAlignment() const
Returns the natural stack alignment, or MaybeAlign() if one wasn't specified.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
StringRef getPrivateGlobalPrefix() const
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Describe properties that are true of each instruction in the target description file.
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
bool is64BitVector() const
Return true if this is a 64-bit vector type.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI unsigned createJumpTableIndex(const std::vector< MachineBasicBlock * > &DestBBs)
createJumpTableIndex - Create a new jump table.
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
This class is used to represent an MLOAD node.
This class is used to represent an MSTORE node.
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
This instruction constructs a fixed permutation of two input vectors.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
StringRef - Represent a constant reference to a string, i.e.
const unsigned char * bytes_end() const
constexpr size_t size() const
size - Get the string size.
const unsigned char * bytes_begin() const
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
Provides information about what library functions are available for the current target.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const
Get the CallingConv that should be used for the specified libcall.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
ShiftLegalizationStrategy
Return the preferred strategy to legalize tihs SHIFT instruction, with ExpansionFactor being the recu...
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
const TargetMachine & getTargetMachine() const
void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked load does or does not work with the specified type and ind...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked store does or does not work with the specified type and in...
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
static StringRef getLibcallImplName(RTLIB::LibcallImpl Call)
Get the libcall routine name for the specified libcall implementation.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl)
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
virtual void insertSSPDeclarations(Module &M) const
Inserts necessary declarations for SSP (stack protection) purpose.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool expandDIVREMByConstant(SDNode *N, SmallVectorImpl< SDValue > &Result, EVT HiLoVT, SelectionDAG &DAG, SDValue LL=SDValue(), SDValue LH=SDValue()) const
Attempt to expand an n-bit div/rem/divrem by constant using a n/2-bit urem by constant and other arit...
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual ArrayRef< MCPhysReg > getRoundingControlRegisters() const
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
ExceptionHandling getExceptionModel() const
Return the ExceptionHandling to use, considering TargetOptions and the Triple's default.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
unsigned EmitCallGraphSection
Emit section containing call graph metadata.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
Base class of all SIMD vector types.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static CondCodes getOppositeCondition(CondCodes CC)
@ SECREL
Thread Pointer Offset.
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
TOF
Target Operand Flag enum.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2Offset(unsigned AM2Opc)
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
AddrOpc getAM2Op(unsigned AM2Opc)
bool isBitFieldInvertedMask(unsigned v)
const unsigned FPStatusBits
const unsigned FPReservedBits
const unsigned RoundingBitsPos
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Swift
Calling convention for Swift.
@ ARM_APCS
ARM Procedure Calling Standard (obsolete, but still used on some targets).
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ ARM_AAPCS
ARM Architecture Procedure Calling Standard calling convention (aka EABI).
@ CXX_FAST_TLS
Used for access functions.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ ARM_AAPCS_VFP
Same as ARM_AAPCS, but uses hard floating point ABI.
@ C
The default llvm calling convention, compatible with C.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
@ FGETSIGN
INT = FGETSIGN(FP) - Return the sign bit of the specified floating point value as an integer 0/1 valu...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ EH_SJLJ_SETUP_DISPATCH
OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) The target initializes the dispatch table here.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ SSUBO
Same for subtraction.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ SMULO
Same for multiplication.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ SjLj
setjmp/longjmp based exceptions
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
FunctionAddr VTableAddr uintptr_t uintptr_t Data
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
bool isUnknown() const
Returns true if we don't know any bits.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)