83#include "llvm/IR/IntrinsicsARM.h"
118#define DEBUG_TYPE "arm-isel"
121STATISTIC(NumOptimizedImms,
"Number of times immediates were optimized");
122STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
123STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
125 "Number of constants with their storage promoted into constant pools");
129 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
134 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
139 cl::desc(
"Maximum size of constant to promote into a constant pool"),
143 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
148 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
153 cl::desc(
"Maximum number of base-updates to check generating postindex."),
161 ARM::R0, ARM::R1, ARM::R2, ARM::R3
175void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
176 if (VT != PromotedLdStVT) {
185 if (ElemTy != MVT::f64)
189 if (ElemTy == MVT::i32) {
233void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
235 addTypeForNEON(VT, MVT::f64);
238void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
240 addTypeForNEON(VT, MVT::v2f64);
243void ARMTargetLowering::setAllExpand(
MVT VT) {
256void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
263void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
264 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
266 for (
auto VT : IntTypes) {
341 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
342 for (
auto VT : FloatTypes) {
416 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
417 for (
auto VT : LongTypes) {
434 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
435 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
436 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
453 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
462 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
463 for (
auto VT : pTypes) {
514 RegInfo(Subtarget->getRegisterInfo()),
515 Itins(Subtarget->getInstrItineraryData()) {
521 const Triple &TT = TM.getTargetTriple();
523 if (Subtarget->isThumb1Only())
528 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
529 Subtarget->hasFPRegs()) {
533 if (!Subtarget->hasVFP2Base()) {
534 setAllExpand(MVT::f32);
543 if (!Subtarget->hasFP64()) {
544 setAllExpand(MVT::f64);
554 if (Subtarget->hasFullFP16()) {
569 if (Subtarget->hasBF16()) {
571 setAllExpand(MVT::bf16);
572 if (!Subtarget->hasFullFP16())
586 addAllExtLoads(VT, InnerVT,
Expand);
595 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
598 if (!Subtarget->hasV8_1MMainlineOps())
601 if (!Subtarget->isThumb1Only())
610 if (Subtarget->hasMVEIntegerOps())
611 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
614 if (Subtarget->hasLOB()) {
618 if (Subtarget->hasNEON()) {
619 addDRTypeForNEON(MVT::v2f32);
620 addDRTypeForNEON(MVT::v8i8);
621 addDRTypeForNEON(MVT::v4i16);
622 addDRTypeForNEON(MVT::v2i32);
623 addDRTypeForNEON(MVT::v1i64);
625 addQRTypeForNEON(MVT::v4f32);
626 addQRTypeForNEON(MVT::v2f64);
627 addQRTypeForNEON(MVT::v16i8);
628 addQRTypeForNEON(MVT::v8i16);
629 addQRTypeForNEON(MVT::v4i32);
630 addQRTypeForNEON(MVT::v2i64);
632 if (Subtarget->hasFullFP16()) {
633 addQRTypeForNEON(MVT::v8f16);
634 addDRTypeForNEON(MVT::v4f16);
637 if (Subtarget->hasBF16()) {
638 addQRTypeForNEON(MVT::v8bf16);
639 addDRTypeForNEON(MVT::v4bf16);
643 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
683 if (Subtarget->hasNEON()) {
796 if (!Subtarget->hasVFP4Base()) {
805 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
814 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
823 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
831 if (Subtarget->hasMVEIntegerOps()) {
836 if (Subtarget->hasMVEFloatOps()) {
840 if (!Subtarget->hasFP64()) {
892 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
895 if (Subtarget->hasFullFP16()) {
903 if (!Subtarget->hasFP16()) {
932 if (!Subtarget->isThumb1Only()) {
951 if (TT.isTargetAEABI() && !Subtarget->allowsUnalignedMem()) {
963 if (!Subtarget->isThumb1Only()) {
972 if (Subtarget->hasDSP()) {
982 if (Subtarget->hasBaseDSP()) {
990 if (Subtarget->isThumb1Only()) {
994 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
995 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1010 if (Subtarget->hasMVEIntegerOps())
1014 if (Subtarget->isThumb1Only()) {
1020 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1034 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1043 if (Subtarget->hasPerfMon())
1047 if (!Subtarget->hasV6Ops())
1050 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1051 : Subtarget->hasDivideInARMMode();
1058 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1070 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1071 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1074 HasStandaloneRem =
false;
1101 if (TT.isOSWindows())
1108 InsertFencesForAtomic =
false;
1109 if (Subtarget->hasAnyDataBarrier() &&
1110 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1114 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1119 if (!Subtarget->hasAcquireRelease() ||
1122 InsertFencesForAtomic =
true;
1128 if (Subtarget->hasDataBarrier())
1129 InsertFencesForAtomic =
true;
1149 if (!InsertFencesForAtomic) {
1156 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1168 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1169 Subtarget->hasForced32BitAtomics()) {
1183 if (!Subtarget->hasV6Ops()) {
1189 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1190 !Subtarget->isThumb1Only()) {
1219 if (Subtarget->hasFullFP16()) {
1229 if (Subtarget->hasFullFP16())
1244 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1245 !Subtarget->isThumb1Only()) {
1252 if (!Subtarget->hasVFP4Base()) {
1258 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1260 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1268 if (!Subtarget->hasFP16()) {
1285 if (Subtarget->hasFPARMv8Base()) {
1295 if (Subtarget->hasFP64())
1299 if (Subtarget->hasNEON()) {
1309 if (Subtarget->hasFullFP16()) {
1346 if (Subtarget->hasNEON()) {
1358 if (Subtarget->hasV8Ops()) {
1368 if (Subtarget->hasFullFP16()) {
1391 if (TT.isOSWindows()) {
1408 if (Subtarget->hasMVEIntegerOps())
1411 if (Subtarget->hasV6Ops())
1413 if (Subtarget->isThumb1Only())
1416 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1417 Subtarget->isThumb2()) {
1423 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1424 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1446 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1454 return Subtarget->useSoftFloat();
1458 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1471std::pair<const TargetRegisterClass *, uint8_t>
1482 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1483 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1484 RRC = &ARM::DPRRegClass;
1489 if (Subtarget->useNEONForSinglePrecisionFP())
1492 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1493 case MVT::v4f32:
case MVT::v2f64:
1494 RRC = &ARM::DPRRegClass;
1498 RRC = &ARM::DPRRegClass;
1502 RRC = &ARM::DPRRegClass;
1506 return std::make_pair(RRC,
Cost);
1515 if (Subtarget->hasMVEIntegerOps())
1530 if (Subtarget->hasNEON()) {
1531 if (VT == MVT::v4i64)
1532 return &ARM::QQPRRegClass;
1533 if (VT == MVT::v8i64)
1534 return &ARM::QQQQPRRegClass;
1536 if (Subtarget->hasMVEIntegerOps()) {
1537 if (VT == MVT::v4i64)
1538 return &ARM::MQQPRRegClass;
1539 if (VT == MVT::v8i64)
1540 return &ARM::MQQQQPRRegClass;
1549 Align &PrefAlign)
const {
1556 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1568 unsigned NumVals =
N->getNumValues();
1572 for (
unsigned i = 0; i != NumVals; ++i) {
1573 EVT VT =
N->getValueType(i);
1574 if (VT == MVT::Glue || VT == MVT::Other)
1580 if (!
N->isMachineOpcode())
1588 if (
MCID.getNumDefs() == 0)
1590 if (!Itins->isEmpty() &&
1591 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1605 return Const->getZExtValue() == 16;
1613 return Const->getZExtValue() == 16;
1621 return Const->getZExtValue() == 16;
1690 bool isVarArg)
const {
1709 if (!Subtarget->isAAPCS_ABI())
1711 else if (Subtarget->isTargetHardFloat() && !isVarArg)
1717 if (!Subtarget->isAAPCS_ABI()) {
1718 if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() && !isVarArg)
1721 }
else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1730 bool isVarArg)
const {
1731 return CCAssignFnForNode(CC,
false, isVarArg);
1735 bool isVarArg)
const {
1736 return CCAssignFnForNode(CC,
true, isVarArg);
1743 bool isVarArg)
const {
1770 if (Subtarget->hasFullFP16()) {
1771 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1783 if (Subtarget->hasFullFP16()) {
1784 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1797SDValue ARMTargetLowering::LowerCallResult(
1801 SDValue ThisVal,
bool isCmseNSCall)
const {
1809 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1810 CCValAssign VA = RVLocs[i];
1814 if (i == 0 && isThisReturn) {
1816 "unexpected return calling convention register assignment");
1834 if (!Subtarget->isLittle())
1836 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1851 if (!Subtarget->isLittle())
1853 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1883 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1894std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1896 bool IsTailCall,
int SPDiff)
const {
1898 MachinePointerInfo DstInfo;
1918 return std::make_pair(DstAddr, DstInfo);
1927ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1940 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1943 int SrcFI = SrcFrameIdxNode->getIndex();
1944 int DstFI = DstFrameIdxNode->getIndex();
1946 "byval passed in non-fixed stack slot");
1968 if (SrcOffset == DstOffset)
1976 RegsToPassVector &RegsToPass,
1983 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1984 unsigned id = Subtarget->isLittle() ? 0 : 1;
1996 MachinePointerInfo DstInfo;
1997 std::tie(DstAddr, DstInfo) =
1998 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2015 SelectionDAG &DAG = CLI.
DAG;
2017 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2018 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2019 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2026 const CallBase *CB = CLI.
CB;
2029 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2031 MachineFunction::CallSiteInfo CSInfo;
2032 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2033 bool isThisReturn =
false;
2034 bool isCmseNSCall =
false;
2035 bool isSibCall =
false;
2036 bool PreferIndirect =
false;
2037 bool GuardWithBTI =
false;
2047 !Subtarget->noBTIAtReturnTwice())
2055 isCmseNSCall =
true;
2058 if (!Subtarget->supportsTailCall())
2074 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2075 count_if(GV->users(), [&BB](
const User *U) {
2076 return isa<Instruction>(U) &&
2077 cast<Instruction>(U)->getParent() == BB;
2084 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2098 "site marked musttail");
2101 unsigned NumBytes = CCInfo.getStackSize();
2110 if (isTailCall && !isSibCall) {
2111 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2112 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2117 assert(StackAlign &&
"data layout string is missing stack alignment");
2118 NumBytes =
alignTo(NumBytes, *StackAlign);
2123 SPDiff = NumReusableBytes - NumBytes;
2127 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2143 RegsToPassVector RegsToPass;
2152 DenseMap<unsigned, SDValue> ByValTemporaries;
2156 for (
const CCValAssign &VA : ArgLocs) {
2158 SDValue Src = OutVals[ArgIdx];
2159 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2161 if (!
Flags.isByVal())
2165 MachinePointerInfo DstInfo;
2166 std::tie(Dst, DstInfo) =
2167 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2168 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2170 if (Copy == NoCopy) {
2175 }
else if (Copy == CopyOnce) {
2179 ByValTemporaries[ArgIdx] = Src;
2181 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2185 int TempFrameIdx = MFI.CreateStackObject(
2186 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2194 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2195 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2197 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2198 ByValTemporaries[ArgIdx] = Temp;
2201 if (!ByValCopyChains.
empty())
2211 bool AfterFormalArgLoads =
false;
2215 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2217 ++i, ++realArgIdx) {
2218 CCValAssign &VA = ArgLocs[i];
2219 SDValue Arg = OutVals[realArgIdx];
2220 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2221 bool isByVal =
Flags.isByVal();
2241 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2243 if (ByValTempChain) {
2248 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2249 if (Outs[
I].
Flags.isByVal())
2257 FrameIndexSDNode *FIN =
2262 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2265 for (
const CCValAssign &VA : ArgLocs) {
2273 if (!IncomingLoad.
empty()) {
2281 AfterFormalArgLoads =
true;
2293 auto ArgVT = Outs[realArgIdx].ArgVT;
2294 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2312 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2313 StackPtr, MemOpChains, isTailCall, SPDiff);
2317 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2318 StackPtr, MemOpChains, isTailCall, SPDiff);
2322 MachinePointerInfo DstInfo;
2323 std::tie(DstAddr, DstInfo) =
2324 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2328 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2329 StackPtr, MemOpChains, isTailCall, SPDiff);
2331 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2332 Outs[0].VT == MVT::i32) {
2334 "unexpected calling convention register assignment");
2336 "unexpected use of 'returned'");
2337 isThisReturn =
true;
2342 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2343 }
else if (isByVal) {
2345 unsigned offset = 0;
2349 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2350 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2353 bool NeedsStackCopy;
2354 if (
auto It = ByValTemporaries.
find(realArgIdx);
2355 It != ByValTemporaries.
end()) {
2356 ByValSrc = It->second;
2357 NeedsStackCopy =
true;
2360 NeedsStackCopy = !isTailCall;
2364 if (CurByValIdx < ByValArgsCount) {
2365 unsigned RegBegin, RegEnd;
2366 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2370 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2374 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2377 RegsToPass.push_back(std::make_pair(j,
Load));
2382 offset = RegEnd - RegBegin;
2384 CCInfo.nextInRegsParam();
2389 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2392 MachinePointerInfo DstInfo;
2393 std::tie(Dst, DstInfo) =
2394 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2402 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2403 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2410 MachinePointerInfo DstInfo;
2411 std::tie(DstAddr, DstInfo) =
2412 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2419 if (!MemOpChains.
empty())
2425 for (
const auto &[
Reg,
N] : RegsToPass) {
2433 bool isDirect =
false;
2436 const Triple &
TT = TM.getTargetTriple();
2437 const GlobalValue *GVal =
nullptr;
2439 GVal =
G->getGlobal();
2440 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2442 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2443 bool isLocalARMFunc =
false;
2446 if (Subtarget->genLongCalls()) {
2448 if (isPIC && Subtarget->genExecuteOnly())
2450 "position-independent code is not supported");
2451 if (Subtarget->isROPI())
2458 if (Subtarget->genExecuteOnly()) {
2461 if (Subtarget->useMovt())
2484 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2490 const char *Sym = S->getSymbol();
2492 if (Subtarget->genExecuteOnly()) {
2495 if (Subtarget->useMovt())
2502 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
2508 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2513 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, GOTOffset, PICLabel);
2525 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2532 if (!PreferIndirect) {
2537 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2539 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2540 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2542 ARMISD::WrapperPIC, dl, PtrVt,
2549 }
else if (Subtarget->isTargetCOFF()) {
2550 assert(Subtarget->isTargetWindows() &&
2551 "Windows is the only supported COFF target");
2555 else if (!TM.shouldAssumeDSOLocal(GVal))
2562 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2571 const char *Sym = S->getSymbol();
2572 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2574 ARMConstantPoolValue *CPV =
2576 ARMPCLabelIndex, 4);
2578 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2583 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2590 assert(!isARMFunc && !isDirect &&
2591 "Cannot handle call to ARM function or direct call");
2595 "call to non-secure function would require "
2596 "passing arguments on stack",
2602 "call to non-secure function would return value through pointer",
2609 if (Subtarget->isThumb()) {
2611 CallOpc = ARMISD::t2CALL_BTI;
2612 else if (isCmseNSCall)
2613 CallOpc = ARMISD::tSECALL;
2614 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2615 CallOpc = ARMISD::CALL_NOLINK;
2617 CallOpc = ARMISD::CALL;
2619 if (!isDirect && !Subtarget->hasV5TOps())
2620 CallOpc = ARMISD::CALL_NOLINK;
2621 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2623 !Subtarget->hasMinSize())
2625 CallOpc = ARMISD::CALL_NOLINK;
2627 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2634 if (isTailCall && !isSibCall) {
2639 std::vector<SDValue>
Ops;
2640 Ops.push_back(Chain);
2641 Ops.push_back(Callee);
2649 for (
const auto &[
Reg,
N] : RegsToPass)
2653 const uint32_t *
Mask;
2654 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2662 isThisReturn =
false;
2668 assert(Mask &&
"Missing call preserved mask for calling convention");
2672 Ops.push_back(InGlue);
2685 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2699 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2705 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2706 InVals, isThisReturn,
2707 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2714void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2715 Align Alignment)
const {
2723 unsigned AlignInRegs =
Alignment.value() / 4;
2724 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2725 for (
unsigned i = 0; i < Waste; ++i)
2731 unsigned Excess = 4 * (ARM::R4 -
Reg);
2738 if (NSAAOffset != 0 &&
Size > Excess) {
2750 unsigned ByValRegBegin =
Reg;
2751 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2755 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2761 Size = std::max<int>(
Size - Excess, 0);
2769bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2775 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2776 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2777 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2778 const SelectionDAG &DAG = CLI.
DAG;
2783 assert(Subtarget->supportsTailCall());
2796 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2798 if (!(Subtarget->isThumb1Only() ||
2799 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2800 AddressRegisters.
insert(ARM::R12);
2801 for (
const CCValAssign &AL : ArgLocs)
2803 AddressRegisters.
erase(
AL.getLocReg());
2804 if (AddressRegisters.
empty()) {
2805 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2824 <<
" (guaranteed tail-call CC)\n");
2825 return CalleeCC == CallerCC;
2830 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2832 if (isCalleeStructRet != isCallerStructRet) {
2845 const GlobalValue *GV =
G->getGlobal();
2848 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2849 TT.isOSBinFormatMachO())) {
2866 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2867 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2868 if (CalleeCC != CallerCC) {
2869 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2870 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2879 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2887 const MachineRegisterInfo &MRI = MF.
getRegInfo();
2889 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2908 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2917 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2930 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2933 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2937 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2942 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2964 bool isLittleEndian = Subtarget->isLittle();
2967 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2976 "secure entry function would return value through pointer",
2981 for (
unsigned i = 0, realRVLocIdx = 0;
2983 ++i, ++realRVLocIdx) {
2984 CCValAssign &VA = RVLocs[i];
2987 SDValue Arg = OutVals[realRVLocIdx];
2988 bool ReturnF16 =
false;
2990 if (Subtarget->hasFullFP16() && Subtarget->isTargetHardFloat()) {
3023 auto RetVT = Outs[realRVLocIdx].ArgVT;
3045 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3049 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3055 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3067 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3069 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3074 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3084 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3110 !Subtarget->isMClass()) {
3111 if (Subtarget->isThumb1Only())
3118 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3121bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3122 if (
N->getNumValues() != 1)
3124 if (!
N->hasNUsesOfValue(1, 0))
3128 SDNode *
Copy = *
N->user_begin();
3132 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3134 TCChain =
Copy->getOperand(0);
3135 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3136 SDNode *VMov =
Copy;
3138 SmallPtrSet<SDNode*, 2>
Copies;
3139 for (SDNode *U : VMov->
users()) {
3147 for (SDNode *U : VMov->
users()) {
3148 SDValue UseChain =
U->getOperand(0);
3156 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3164 if (!
Copy->hasOneUse())
3171 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3173 TCChain =
Copy->getOperand(0);
3178 bool HasRet =
false;
3179 for (
const SDNode *U :
Copy->users()) {
3180 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3181 U->getOpcode() != ARMISD::INTRET_GLUE)
3193bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3194 if (!Subtarget->supportsTailCall())
3211 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3227 EVT PtrVT =
Op.getValueType();
3237 if (Subtarget->genExecuteOnly()) {
3242 auto GV =
new GlobalVariable(
3248 return LowerGlobalAddress(GA, DAG);
3254 if (Subtarget->isThumb1Only())
3255 CPAlign = std::max(CPAlign,
Align(4));
3261 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3268 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3277 unsigned ARMPCLabelIndex = 0;
3283 if (!IsPositionIndependent) {
3286 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3293 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3297 if (!IsPositionIndependent)
3300 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3328ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3331 "This function expects a Darwin target");
3336 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3342 MVT::i32,
DL, Chain, DescAddr,
3357 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3366 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3372ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3375 "Windows specific TLS lowering");
3399 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3407 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3408 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3414 MachinePointerInfo());
3421 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3434 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3436 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3438 ARMConstantPoolValue *CPV =
3449 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3456 TargetLowering::CallLoweringInfo CLI(DAG);
3461 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3462 return CallResult.first;
3471 const GlobalValue *GV = GA->
getGlobal();
3477 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3481 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3484 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3485 ARMConstantPoolValue *CPV =
3492 PtrVT, dl, Chain,
Offset,
3500 PtrVT, dl, Chain,
Offset,
3505 ARMConstantPoolValue *CPV =
3510 PtrVT, dl, Chain,
Offset,
3526 if (
TT.isOSDarwin())
3527 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3529 if (
TT.isOSWindows())
3530 return LowerGlobalTLSAddressWindows(
Op, DAG);
3533 assert(
TT.isOSBinFormatELF() &&
"Only ELF implemented here");
3539 return LowerToTLSGeneralDynamicModel(GA, DAG);
3542 return LowerToTLSExecModels(GA, DAG, model);
3551 while (!Worklist.
empty()) {
3559 if (!
I ||
I->getParent()->getParent() !=
F)
3588 if (!GVar || !GVar->hasInitializer() ||
3589 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3590 !GVar->hasLocalLinkage())
3595 auto *
Init = GVar->getInitializer();
3597 Init->needsDynamicRelocation())
3609 unsigned RequiredPadding = 4 - (
Size % 4);
3610 bool PaddingPossible =
3611 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3616 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3640 if (RequiredPadding != 4) {
3645 while (RequiredPadding--)
3657 ++NumConstpoolPromoted;
3658 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3663 if (!(GV = GA->getAliaseeObject()))
3666 return V->isConstant();
3675 return LowerGlobalAddressWindows(
Op, DAG);
3677 return LowerGlobalAddressELF(
Op, DAG);
3679 return LowerGlobalAddressDarwin(
Op, DAG);
3691 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3704 }
else if (Subtarget->isROPI() && IsRO) {
3709 }
else if (Subtarget->isRWPI() && !IsRO) {
3712 if (Subtarget->useMovt()) {
3715 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3717 ARMConstantPoolValue *CPV =
3720 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3734 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3735 if (Subtarget->useMovt())
3739 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3743 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3752 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3753 "ROPI/RWPI not currently supported for Darwin");
3758 if (Subtarget->useMovt())
3769 if (Subtarget->isGVIndirectSymbol(GV))
3778 "non-Windows COFF is not supported");
3779 assert(Subtarget->useMovt() &&
3780 "Windows on ARM expects to use movw/movt");
3781 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3782 "ROPI/RWPI not currently supported for Windows");
3789 else if (!TM.shouldAssumeDSOLocal(GV))
3812 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3813 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3814 Op.getOperand(1), Val);
3820 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3827 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3831SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3834 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3838 case Intrinsic::arm_gnu_eabi_mcount: {
3844 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3845 const uint32_t *
Mask =
3847 assert(Mask &&
"Missing call preserved mask for calling convention");
3852 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3856 if (Subtarget->isThumb())
3859 ARM::tBL_PUSHLR, dl, ResultTys,
3860 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3861 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3865 {ReturnAddress, Callee, RegisterMask, Chain}),
3874 unsigned IntNo =
Op.getConstantOperandVal(0);
3878 case Intrinsic::localaddress: {
3880 const auto *RegInfo = Subtarget->getRegisterInfo();
3881 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
3883 Op.getSimpleValueType());
3885 case Intrinsic::eh_recoverfp: {
3891 "llvm.eh.recoverfp must take a function as the first argument");
3892 const auto *RegInfo = Subtarget->getRegisterInfo();
3895 MachineBasicBlock &
MBB = *MF.
begin();
3901 case Intrinsic::thread_pointer: {
3903 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3905 case Intrinsic::arm_cls: {
3909 const SDValue &Operand =
Op.getOperand(1);
3910 const EVT VTy =
Op.getValueType();
3913 case Intrinsic::arm_cls64: {
3919 case Intrinsic::arm_neon_vcls:
3920 case Intrinsic::arm_mve_vcls: {
3923 const EVT VTy =
Op.getValueType();
3926 case Intrinsic::eh_sjlj_lsda: {
3928 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3933 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3934 ARMConstantPoolValue *CPV =
3938 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3943 if (IsPositionIndependent) {
3945 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3949 case Intrinsic::arm_neon_vabs:
3952 case Intrinsic::arm_neon_vabds:
3953 if (
Op.getValueType().isInteger())
3955 Op.getOperand(1),
Op.getOperand(2));
3957 case Intrinsic::arm_neon_vabdu:
3959 Op.getOperand(1),
Op.getOperand(2));
3960 case Intrinsic::arm_neon_vmulls:
3961 case Intrinsic::arm_neon_vmullu: {
3962 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3963 ? ARMISD::VMULLs : ARMISD::VMULLu;
3964 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3965 Op.getOperand(1),
Op.getOperand(2));
3967 case Intrinsic::arm_neon_vminnm:
3968 case Intrinsic::arm_neon_vmaxnm: {
3969 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3971 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3972 Op.getOperand(1),
Op.getOperand(2));
3974 case Intrinsic::arm_neon_vminu:
3975 case Intrinsic::arm_neon_vmaxu: {
3976 if (
Op.getValueType().isFloatingPoint())
3978 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3980 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3981 Op.getOperand(1),
Op.getOperand(2));
3983 case Intrinsic::arm_neon_vmins:
3984 case Intrinsic::arm_neon_vmaxs: {
3986 if (!
Op.getValueType().isFloatingPoint()) {
3987 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3989 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3990 Op.getOperand(1),
Op.getOperand(2));
3992 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3994 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3995 Op.getOperand(1),
Op.getOperand(2));
3997 case Intrinsic::arm_neon_vtbl1:
3998 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
3999 Op.getOperand(1),
Op.getOperand(2));
4000 case Intrinsic::arm_neon_vtbl2:
4001 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
4002 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4003 case Intrinsic::arm_mve_pred_i2v:
4004 case Intrinsic::arm_mve_pred_v2i:
4005 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
4007 case Intrinsic::arm_mve_vreinterpretq:
4008 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
4010 case Intrinsic::arm_mve_lsll:
4011 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
4012 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4013 case Intrinsic::arm_mve_asrl:
4014 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
4015 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4016 case Intrinsic::arm_mve_vsli:
4017 return DAG.
getNode(ARMISD::VSLIIMM, SDLoc(
Op),
Op->getVTList(),
4018 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4019 case Intrinsic::arm_mve_vsri:
4020 return DAG.
getNode(ARMISD::VSRIIMM, SDLoc(
Op),
Op->getVTList(),
4021 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4032 if (!Subtarget->hasDataBarrier()) {
4036 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4037 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4038 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
4048 }
else if (Subtarget->preferISHSTBarriers() &&
4057 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4065 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4067 return Op.getOperand(0);
4070 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4072 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4074 return Op.getOperand(0);
4076 unsigned isData =
Op.getConstantOperandVal(4);
4077 if (Subtarget->isThumb()) {
4079 isRead = ~isRead & 1;
4080 isData = ~isData & 1;
4083 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4098 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4106 const SDLoc &dl)
const {
4108 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4112 RC = &ARM::tGPRRegClass;
4114 RC = &ARM::GPRRegClass;
4128 MVT::i32, dl, Root, FIN,
4134 if (!Subtarget->isLittle())
4136 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4149 const Value *OrigArg,
4150 unsigned InRegsParamRecordIdx,
4151 int ArgOffset,
unsigned ArgSize)
const {
4165 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4166 unsigned RBegin, REnd;
4171 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4176 ArgOffset = -4 * (ARM::R4 - RBegin);
4186 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4190 MachinePointerInfo(OrigArg, 4 * i));
4195 if (!MemOps.
empty())
4204 unsigned TotalArgRegsSaveSize,
4205 bool ForceMutable)
const {
4207 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4216 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4220bool ARMTargetLowering::splitValueIntoRegisterParts(
4222 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4224 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4236SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4238 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4239 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4252SDValue ARMTargetLowering::LowerFormalArguments(
4259 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4268 unsigned CurArgIdx = 0;
4280 unsigned ArgRegBegin = ARM::R4;
4281 for (
const CCValAssign &VA : ArgLocs) {
4287 if (!
Flags.isByVal())
4291 unsigned RBegin, REnd;
4293 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4299 int lastInsIndex = -1;
4303 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4306 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4310 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4311 CCValAssign &VA = ArgLocs[i];
4312 if (Ins[VA.
getValNo()].isOrigArg()) {
4313 std::advance(CurOrigArg,
4314 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4315 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4326 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4333 MVT::f64, dl, Chain, FIN,
4336 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4344 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4348 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4349 RC = &ARM::HPRRegClass;
4350 else if (RegVT == MVT::f32)
4351 RC = &ARM::SPRRegClass;
4352 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4353 RegVT == MVT::v4bf16)
4354 RC = &ARM::DPRRegClass;
4355 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4356 RegVT == MVT::v8bf16)
4357 RC = &ARM::QPRRegClass;
4358 else if (RegVT == MVT::i32)
4360 : &ARM::GPRRegClass;
4397 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4406 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4412 if (index != lastInsIndex)
4414 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4420 if (
Flags.isByVal()) {
4421 assert(Ins[index].isOrigArg() &&
4422 "Byval arguments cannot be implicit");
4426 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4460 lastInsIndex = index;
4467 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4468 TotalArgRegsSaveSize);
4472 "secure entry function must not be variadic", dl.
getDebugLoc()));
4482 assert(StackAlign &&
"data layout string is missing stack alignment");
4483 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4492 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4501 return CFP->getValueAPF().isPosZero();
4504 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4505 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4508 return CFP->getValueAPF().isPosZero();
4511 Op->getValueType(0) == MVT::f64) {
4515 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4524 if (
Op->getFlags().hasNoSignedWrap())
4540 (isIntEqualitySetCC(CC) ||
4550 if (ST.isThumb1Only() || !
Op.hasOneUse())
4553 unsigned Opc =
Op.getOpcode();
4556 return ShiftAmt->getZExtValue() <= 31 ? 1 : 0;
4559 return ST.isThumb() ? 0 : 1;
4567 return ST.isThumb() ? 0 : 1;
4577 const SDLoc &dl)
const {
4579 unsigned C = RHSC->getZExtValue();
4637 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4641 unsigned Mask =
LHS.getConstantOperandVal(1);
4643 uint64_t RHSV = RHSC->getZExtValue();
4644 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4646 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4660 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4663 LHS.getConstantOperandVal(1) < 31) {
4664 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4674 unsigned CompareType;
4677 CompareType = ARMISD::CMP;
4682 CompareType = ARMISD::CMPZ;
4691 if (CompareType != ARMISD::CMPZ &&
isCMN(
RHS, CC, DAG)) {
4692 CompareType = ARMISD::CMN;
4694 }
else if (CompareType != ARMISD::CMPZ &&
isCMN(
LHS, CC, DAG)) {
4695 CompareType = ARMISD::CMN;
4709 if (CompareType == ARMISD::CMP)
4737 bool Signaling)
const {
4738 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4744 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4753std::pair<SDValue, SDValue>
4756 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4768 switch (
Op.getOpcode()) {
4820 return std::make_pair(
Value, OverflowCmp);
4833 return Cmp.getValue(1);
4861 return DAG.
getNode(ARMISD::CMOV,
DL, VT, Zero, One, ARMcc, Flags);
4873 EVT VT =
Op.getValueType();
4874 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4877 switch (
Op.getOpcode()) {
4891 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4897 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4900 ARMcc, OverflowCmp);
4910 EVT VT =
Op.getValueType();
4911 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4921 switch (
Op->getOpcode()) {
4923 NewOpcode = ARMISD::UQADD8b;
4926 NewOpcode = ARMISD::QADD8b;
4929 NewOpcode = ARMISD::UQSUB8b;
4932 NewOpcode = ARMISD::QSUB8b;
4937 switch (
Op->getOpcode()) {
4939 NewOpcode = ARMISD::UQADD16b;
4942 NewOpcode = ARMISD::QADD16b;
4945 NewOpcode = ARMISD::UQSUB16b;
4948 NewOpcode = ARMISD::QSUB16b;
4956 DAG.
getNode(NewOpcode, dl, MVT::i32,
4967 unsigned Opc =
Cond.getOpcode();
4969 if (
Cond.getResNo() == 1 &&
4977 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4978 EVT VT =
Op.getValueType();
4980 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4988 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4989 const ConstantSDNode *CMOVTrue =
4991 const ConstantSDNode *CMOVFalse =
4994 if (CMOVTrue && CMOVFalse) {
5000 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5002 False = SelectFalse;
5003 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5009 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5010 Cond.getOperand(3), DAG);
5020 bool &swpCmpOps,
bool &swpVselOps) {
5048 swpCmpOps = !swpCmpOps;
5049 swpVselOps = !swpVselOps;
5072 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5074 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5076 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5090 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5111 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5113 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5134 EVT VT =
Op.getValueType();
5156 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5169 int64_t PosVal = std::max(Val1, Val2);
5170 int64_t NegVal = std::min(Val1, Val2);
5182 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5185 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5217 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5222 if (*K != KTmp || V != VTmp)
5233bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5235 return !Subtarget->hasVFP2Base();
5237 return !Subtarget->hasFP64();
5239 return !Subtarget->hasFullFP16();
5247 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5255 if (TVal == ~FVal) {
5256 Opcode = ARMISD::CSINV;
5257 }
else if (TVal == ~FVal + 1) {
5258 Opcode = ARMISD::CSNEG;
5259 }
else if (TVal + 1 == FVal) {
5260 Opcode = ARMISD::CSINC;
5261 }
else if (TVal == FVal + 1) {
5262 Opcode = ARMISD::CSINC;
5265 InvertCond = !InvertCond;
5272 if (Opcode != ARMISD::CSINC &&
5276 InvertCond = !InvertCond;
5282 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5285 InvertCond = !InvertCond;
5292 EVT VT =
Op.getValueType();
5296 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5308 if (VT == MVT::i32 &&
5327 if (
Op.getValueType().isInteger()) {
5335 LHS.getValueType() ==
RHS.getValueType()) {
5336 EVT VT =
LHS.getValueType();
5342 Shift = DAG.
getNOT(dl, Shift, VT);
5354 if (
LHS.getValueType() == MVT::i32) {
5358 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5364 EVT VT =
Op.getValueType();
5365 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5369 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5374 if (!
RHS.getNode()) {
5380 if (
LHS.getValueType() == MVT::i32) {
5391 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5392 TrueVal.getValueType() == MVT::f32 ||
5393 TrueVal.getValueType() == MVT::f64)) {
5407 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5417 if (Subtarget->hasFPARMv8Base() &&
5419 (
TrueVal.getValueType() == MVT::f16 ||
5420 TrueVal.getValueType() == MVT::f32 ||
5421 TrueVal.getValueType() == MVT::f64)) {
5422 bool swpCmpOps =
false;
5423 bool swpVselOps =
false;
5437 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5440 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5450 if (!
N->hasOneUse())
5453 if (!
N->getNumValues())
5455 EVT VT =
Op.getValueType();
5456 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5473 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5474 Ld->getPointerInfo(), Ld->getAlign(),
5475 Ld->getMemOperand()->getFlags());
5491 SDValue Ptr = Ld->getBasePtr();
5493 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5494 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5499 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5500 Ld->getPointerInfo().getWithOffset(4),
5502 Ld->getMemOperand()->getFlags());
5520 bool LHSSeenZero =
false;
5522 bool RHSSeenZero =
false;
5524 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5535 if (
LHS.getValueType() == MVT::f32) {
5541 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5553 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5554 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5569 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5588 unsigned Opc =
Cond.getOpcode();
5590 !Subtarget->isThumb1Only();
5591 if (
Cond.getResNo() == 1 &&
5601 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5606 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5621 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5626 if (!
RHS.getNode()) {
5634 unsigned Opc =
LHS.getOpcode();
5636 !Subtarget->isThumb1Only();
5648 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5655 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5659 if (
LHS.getValueType() == MVT::i32) {
5662 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5665 SDNodeFlags
Flags =
Op->getFlags();
5666 if (
Flags.hasNoNaNs() &&
5671 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5685 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5699 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5702 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5707 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5708 Addr,
Op.getOperand(2), JTI);
5712 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5716 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5719 DAG.
getLoad(PTy, dl, Chain, Addr,
5722 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5727 EVT VT =
Op.getValueType();
5730 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5731 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5739 const EVT OpTy =
Op.getOperand(0).getValueType();
5740 if (
OpTy == MVT::v4f32)
5742 else if (
OpTy == MVT::v4f16 && HasFullFP16)
5744 else if (
OpTy == MVT::v8f16 && HasFullFP16)
5749 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5752 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5757 EVT VT =
Op.getValueType();
5761 bool IsStrict =
Op->isStrictFPOpcode();
5762 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5764 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5777 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5778 CallOptions, Loc, Chain);
5787 EVT VT =
Op.getValueType();
5789 EVT FromVT =
Op.getOperand(0).getValueType();
5791 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5793 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5794 Subtarget->hasFP64())
5796 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5797 Subtarget->hasFullFP16())
5799 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5800 Subtarget->hasMVEFloatOps())
5802 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5803 Subtarget->hasMVEFloatOps())
5806 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5823 EVT VT =
Op.getValueType();
5826 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5832 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5833 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5834 "Invalid type for custom lowering!");
5839 if (VT == MVT::v4f32)
5840 DestVecType = MVT::v4i32;
5841 else if (VT == MVT::v4f16 && HasFullFP16)
5842 DestVecType = MVT::v4i16;
5843 else if (VT == MVT::v8f16 && HasFullFP16)
5844 DestVecType = MVT::v8i16;
5850 switch (
Op.getOpcode()) {
5862 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5867 EVT VT =
Op.getValueType();
5871 bool IsStrict =
Op->isStrictFPOpcode();
5872 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5874 if (isUnsupportedFloatingType(VT)) {
5885 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5886 CallOptions, Loc, Chain);
5898 EVT VT =
Op.getValueType();
5902 bool UseNEON = !InGPR && Subtarget->hasNEON();
5909 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5916 if (SrcVT == MVT::f32) {
5919 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5922 }
else if (VT == MVT::f32)
5923 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5938 if (VT == MVT::f32) {
5950 if (SrcVT == MVT::f64)
5959 if (VT == MVT::f32) {
5972 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5980 EVT VT =
Op.getValueType();
5982 unsigned Depth =
Op.getConstantOperandVal(0);
5984 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5988 MachinePointerInfo());
5997 const ARMBaseRegisterInfo &ARI =
5998 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
6003 EVT VT =
Op.getValueType();
6005 unsigned Depth =
Op.getConstantOperandVal(0);
6010 MachinePointerInfo());
6018 return StringSwitch<Register>(
RegName)
6019 .Case(
"sp", ARM::SP)
6030 assert(
N->getValueType(0) == MVT::i64
6031 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6034 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6074 const APInt &APIntIndex = Index->getAPIntValue();
6076 NewIndex *= APIntIndex;
6105 EVT SrcVT =
Op.getValueType();
6106 EVT DstVT =
N->getValueType(0);
6108 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6109 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6110 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6113 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6114 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6115 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6122 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6134 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6142 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6144 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6146 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6166 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6175 EVT VT =
Op.getValueType();
6197 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6207 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6218 EVT VT =
Op.getValueType();
6239 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6260 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6312 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6340 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6370 EVT VT =
N->getValueType(0);
6371 if (VT.
isVector() && ST->hasNEON()) {
6380 if (ElemTy == MVT::i8) {
6388 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6391 unsigned NumBits = ElemTy.getSizeInBits();
6393 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6403 if (ElemTy == MVT::i64) {
6416 if (!ST->hasV6T2Ops())
6425 EVT VT =
N->getValueType(0);
6428 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6429 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6430 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6431 "Unexpected type for custom ctpop lowering");
6439 unsigned EltSize = 8;
6462 Op =
Op.getOperand(0);
6464 APInt SplatBits, SplatUndef;
6465 unsigned SplatBitSize;
6468 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6470 SplatBitSize > ElementBits)
6481 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6485 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6496 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6501 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6502 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6511 EVT VT =
N->getValueType(0);
6526 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6528 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6533 "unexpected vector shift opcode");
6535 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6536 unsigned VShiftOpc =
6537 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6538 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6544 EVT ShiftVT =
N->getOperand(1).getValueType();
6547 unsigned VShiftOpc =
6548 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6549 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6554 EVT VT =
N->getValueType(0);
6563 "Unknown shift to lower!");
6565 unsigned ShOpc =
N->getOpcode();
6566 if (ST->hasMVEIntegerOps()) {
6568 unsigned ShPartsOpc = ARMISD::LSLL;
6589 ShPartsOpc = ARMISD::LSRL;
6591 ShPartsOpc = ARMISD::ASRL;
6596 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6610 if (ST->isThumb1Only())
6615 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6619 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6623 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6631 bool Invert =
false;
6638 EVT VT =
Op.getValueType();
6646 assert(ST->hasMVEIntegerOps() &&
6647 "No hardware support for integer vector comparison!");
6649 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6670 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6674 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6684 switch (SetCCOpcode) {
6688 if (ST->hasMVEFloatOps()) {
6691 Invert =
true; [[fallthrough]];
6696 case ISD::SETLT: Swap =
true; [[fallthrough]];
6700 case ISD::SETLE: Swap =
true; [[fallthrough]];
6716 Result = DAG.
getNOT(dl, Result, VT);
6719 case ISD::SETUO: Invert =
true; [[fallthrough]];
6728 Result = DAG.
getNOT(dl, Result, VT);
6734 switch (SetCCOpcode) {
6737 if (ST->hasMVEIntegerOps()) {
6740 Invert =
true; [[fallthrough]];
6743 case ISD::SETLT: Swap =
true; [[fallthrough]];
6745 case ISD::SETLE: Swap =
true; [[fallthrough]];
6762 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6765 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6770 Result = DAG.
getNOT(dl, Result, VT);
6795 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6798 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6804 Result = DAG.
getNOT(dl, Result, VT);
6813 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6830 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6841 unsigned OpCmode,
Imm;
6852 switch (SplatBitSize) {
6857 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6860 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6865 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6866 if ((SplatBits & ~0xff) == 0) {
6872 if ((SplatBits & ~0xff00) == 0) {
6875 Imm = SplatBits >> 8;
6885 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6886 if ((SplatBits & ~0xff) == 0) {
6892 if ((SplatBits & ~0xff00) == 0) {
6895 Imm = SplatBits >> 8;
6898 if ((SplatBits & ~0xff0000) == 0) {
6901 Imm = SplatBits >> 16;
6904 if ((SplatBits & ~0xff000000) == 0) {
6907 Imm = SplatBits >> 24;
6914 if ((SplatBits & ~0xffff) == 0 &&
6915 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6918 Imm = SplatBits >> 8;
6926 if ((SplatBits & ~0xffffff) == 0 &&
6927 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6930 Imm = SplatBits >> 16;
6946 unsigned ImmMask = 1;
6948 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6949 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6951 }
else if ((SplatBits & BitMask) != 0) {
6960 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6974 EVT VT =
Op.getValueType();
6975 bool IsDouble = (VT == MVT::f64);
6981 if (
ST->genExecuteOnly()) {
6983 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6984 "Unexpected architecture");
7002 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
7007 if (!
ST->hasVFP3Base())
7012 if (IsDouble && !Subtarget->hasFP64())
7019 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7037 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7046 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7100 unsigned ExpectedElt =
Imm;
7101 for (
unsigned i = 1; i < NumElts; ++i) {
7105 if (ExpectedElt == NumElts)
7108 if (M[i] < 0)
continue;
7109 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7117 bool &ReverseVEXT,
unsigned &
Imm) {
7119 ReverseVEXT =
false;
7130 unsigned ExpectedElt =
Imm;
7131 for (
unsigned i = 1; i < NumElts; ++i) {
7135 if (ExpectedElt == NumElts * 2) {
7140 if (M[i] < 0)
continue;
7141 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7156 return VT == MVT::v8i8 && M.size() == 8;
7161 if (Mask.size() == Elements * 2)
7162 return Index / Elements;
7163 return Mask[Index] == 0 ? 0 : 1;
7193 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7201 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7203 for (
unsigned j = 0; j < NumElts; j += 2) {
7204 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7205 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7210 if (M.size() == NumElts*2)
7225 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7228 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7230 for (
unsigned j = 0; j < NumElts; j += 2) {
7231 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7232 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7237 if (M.size() == NumElts*2)
7257 if (M.size() != NumElts && M.size() != NumElts*2)
7260 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7262 for (
unsigned j = 0; j < NumElts; ++j) {
7263 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7268 if (M.size() == NumElts*2)
7287 if (M.size() != NumElts && M.size() != NumElts*2)
7290 unsigned Half = NumElts / 2;
7291 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7293 for (
unsigned j = 0; j < NumElts; j += Half) {
7294 unsigned Idx = WhichResult;
7295 for (
unsigned k = 0; k < Half; ++k) {
7296 int MIdx = M[i + j + k];
7297 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7304 if (M.size() == NumElts*2)
7328 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7331 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7333 unsigned Idx = WhichResult * NumElts / 2;
7334 for (
unsigned j = 0; j < NumElts; j += 2) {
7335 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7336 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7342 if (M.size() == NumElts*2)
7361 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7364 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7366 unsigned Idx = WhichResult * NumElts / 2;
7367 for (
unsigned j = 0; j < NumElts; j += 2) {
7368 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7369 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7375 if (M.size() == NumElts*2)
7388 unsigned &WhichResult,
7391 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7392 return ARMISD::VTRN;
7393 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7394 return ARMISD::VUZP;
7395 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7396 return ARMISD::VZIP;
7400 return ARMISD::VTRN;
7402 return ARMISD::VUZP;
7404 return ARMISD::VZIP;
7413 if (NumElts != M.size())
7417 for (
unsigned i = 0; i != NumElts; ++i)
7418 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7427 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7435 int Ofs = Top ? 1 : 0;
7436 int Upper = SingleSource ? 0 : NumElts;
7437 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7438 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7440 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7449 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7458 unsigned Offset = Top ? 0 : 1;
7459 unsigned N = SingleSource ? 0 : NumElts;
7460 for (
unsigned i = 0; i < NumElts; i += 2) {
7461 if (M[i] >= 0 && M[i] != (
int)i)
7463 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7472 if (NumElts != M.size())
7480 unsigned Off0 = rev ? NumElts / 2 : 0;
7481 unsigned Off1 = rev ? 0 : NumElts / 2;
7482 for (
unsigned i = 0; i < NumElts; i += 2) {
7483 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7485 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7501 if (!ST->hasMVEFloatOps())
7506 if (VT != MVT::v8f16)
7527 for (
unsigned i = 1; i < 4; i++) {
7542 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7554 if (!ST->hasMVEFloatOps())
7559 if (VT != MVT::v4f32)
7575 for (
unsigned i = 1; i < 4; i++) {
7586 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7598 Val =
N->getAsZExtVal();
7600 if (ST->isThumb1Only()) {
7601 if (Val <= 255 || ~Val <= 255)
7613 EVT VT =
Op.getValueType();
7615 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7619 unsigned BitsPerBool;
7623 }
else if (NumElts == 4) {
7626 }
else if (NumElts == 8) {
7629 }
else if (NumElts == 16) {
7640 return U.get().isUndef() || U.get() == FirstOp;
7644 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7648 unsigned Bits32 = 0;
7649 for (
unsigned i = 0; i < NumElts; ++i) {
7653 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7655 Bits32 |= BoolMask << (i * BitsPerBool);
7661 for (
unsigned i = 0; i < NumElts; ++i) {
7674 if (!ST->hasMVEIntegerOps())
7678 EVT VT =
Op.getValueType();
7688 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7692 for (
unsigned I = 2;
I < NumElts;
I++) {
7708 switch (
N->getOpcode()) {
7719 return N->getOperand(1).getNode() ==
Op;
7721 switch (
N->getConstantOperandVal(0)) {
7722 case Intrinsic::arm_mve_add_predicated:
7723 case Intrinsic::arm_mve_mul_predicated:
7724 case Intrinsic::arm_mve_qadd_predicated:
7725 case Intrinsic::arm_mve_vhadd:
7726 case Intrinsic::arm_mve_hadd_predicated:
7727 case Intrinsic::arm_mve_vqdmulh:
7728 case Intrinsic::arm_mve_qdmulh_predicated:
7729 case Intrinsic::arm_mve_vqrdmulh:
7730 case Intrinsic::arm_mve_qrdmulh_predicated:
7731 case Intrinsic::arm_mve_vqdmull:
7732 case Intrinsic::arm_mve_vqdmull_predicated:
7734 case Intrinsic::arm_mve_sub_predicated:
7735 case Intrinsic::arm_mve_qsub_predicated:
7736 case Intrinsic::arm_mve_vhsub:
7737 case Intrinsic::arm_mve_hsub_predicated:
7738 return N->getOperand(2).getNode() ==
Op;
7753 EVT VT =
Op.getValueType();
7761 APInt SplatBits, SplatUndef;
7762 unsigned SplatBitSize;
7764 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7771 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7773 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7774 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7775 : SplatBitSize == 16 ? MVT::v8i16
7779 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7782 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7783 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7788 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7792 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7796 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7798 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7802 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7806 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7810 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7816 if (
ST->hasMVEIntegerOps() &&
7817 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7818 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7819 : SplatBitSize == 16 ? MVT::v8i16
7823 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7836 bool isOnlyLowElement =
true;
7837 bool usesOnlyOneValue =
true;
7838 bool hasDominantValue =
false;
7843 DenseMap<SDValue, unsigned> ValueCounts;
7845 for (
unsigned i = 0; i < NumElts; ++i) {
7850 isOnlyLowElement =
false;
7854 unsigned &
Count = ValueCounts[
V];
7857 if (++
Count > (NumElts / 2)) {
7858 hasDominantValue =
true;
7862 if (ValueCounts.
size() != 1)
7863 usesOnlyOneValue =
false;
7864 if (!
Value.getNode() && !ValueCounts.
empty())
7867 if (ValueCounts.
empty())
7873 (VT != MVT::v8f16 ||
ST->hasFullFP16()))
7880 if (hasDominantValue && EltSize <= 32) {
7889 ConstantSDNode *constIndex;
7896 if (VT !=
Value->getOperand(0).getValueType()) {
7899 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7904 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7909 if (!usesOnlyOneValue) {
7912 for (
unsigned I = 0;
I < NumElts; ++
I) {
7917 Ops.push_back(
Op.getOperand(
I));
7927 assert(FVT == MVT::f32 || FVT == MVT::f16);
7928 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7929 for (
unsigned i = 0; i < NumElts; ++i)
7934 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7938 if (usesOnlyOneValue) {
7941 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7965 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7985 if (EltSize >= 32) {
7991 for (
unsigned i = 0; i < NumElts; ++i)
8004 (VT == MVT::v8f16 && !
ST->hasFullFP16())) {
8006 for (
unsigned i = 0 ; i < NumElts; ++i) {
8025 EVT VT =
Op.getValueType();
8028 struct ShuffleSourceInfo {
8030 unsigned MinElt = std::numeric_limits<unsigned>::max();
8031 unsigned MaxElt = 0;