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 (Subtarget->isThumb1Only())
526 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
527 Subtarget->hasFPRegs()) {
536 if (!Subtarget->hasVFP2Base()) {
537 setAllExpand(MVT::f32);
543 if (!Subtarget->hasFP64()) {
544 setAllExpand(MVT::f64);
552 if (Subtarget->hasFullFP16()) {
561 if (Subtarget->hasBF16()) {
563 setAllExpand(MVT::bf16);
564 if (!Subtarget->hasFullFP16())
576 addAllExtLoads(VT, InnerVT,
Expand);
585 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
588 if (!Subtarget->hasV8_1MMainlineOps())
591 if (!Subtarget->isThumb1Only())
600 if (Subtarget->hasMVEIntegerOps())
601 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
604 if (Subtarget->hasLOB()) {
608 if (Subtarget->hasNEON()) {
609 addDRTypeForNEON(MVT::v2f32);
610 addDRTypeForNEON(MVT::v8i8);
611 addDRTypeForNEON(MVT::v4i16);
612 addDRTypeForNEON(MVT::v2i32);
613 addDRTypeForNEON(MVT::v1i64);
615 addQRTypeForNEON(MVT::v4f32);
616 addQRTypeForNEON(MVT::v2f64);
617 addQRTypeForNEON(MVT::v16i8);
618 addQRTypeForNEON(MVT::v8i16);
619 addQRTypeForNEON(MVT::v4i32);
620 addQRTypeForNEON(MVT::v2i64);
622 if (Subtarget->hasFullFP16()) {
623 addQRTypeForNEON(MVT::v8f16);
624 addDRTypeForNEON(MVT::v4f16);
627 if (Subtarget->hasBF16()) {
628 addQRTypeForNEON(MVT::v8bf16);
629 addDRTypeForNEON(MVT::v4bf16);
633 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
673 if (Subtarget->hasNEON()) {
714 ISD::FRINT, ISD::FTRUNC, ISD::FROUNDEVEN}) {
786 if (!Subtarget->hasVFP4Base()) {
795 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
804 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
813 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
821 if (Subtarget->hasMVEIntegerOps()) {
826 if (Subtarget->hasMVEFloatOps()) {
830 if (!Subtarget->hasFP64()) {
875 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
878 if (Subtarget->hasFullFP16()) {
884 if (!Subtarget->hasFP16()) {
910 if (!Subtarget->isThumb1Only()) {
935 if (Subtarget->hasDSP()) {
945 if (Subtarget->hasBaseDSP()) {
953 if (Subtarget->isThumb1Only()) {
957 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
958 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
973 if (Subtarget->hasMVEIntegerOps())
977 if (Subtarget->isThumb1Only()) {
983 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
997 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1006 if (Subtarget->hasPerfMon())
1010 if (!Subtarget->hasV6Ops())
1013 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1014 : Subtarget->hasDivideInARMMode();
1021 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1033 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1034 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1037 HasStandaloneRem =
false;
1064 if (TT.isOSWindows())
1071 InsertFencesForAtomic =
false;
1072 if (Subtarget->hasAnyDataBarrier() &&
1073 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1077 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1082 if (!Subtarget->hasAcquireRelease() ||
1085 InsertFencesForAtomic =
true;
1091 if (Subtarget->hasDataBarrier())
1092 InsertFencesForAtomic =
true;
1112 if (!InsertFencesForAtomic) {
1119 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1131 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1132 Subtarget->hasForced32BitAtomics()) {
1146 if (!Subtarget->hasV6Ops()) {
1152 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1153 !Subtarget->isThumb1Only()) {
1182 if (Subtarget->hasFullFP16()) {
1192 if (Subtarget->hasFullFP16())
1207 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1208 !Subtarget->isThumb1Only()) {
1215 if (!Subtarget->hasVFP4Base()) {
1221 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1223 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1231 if (!Subtarget->hasFP16()) {
1251 if (Subtarget->hasFPARMv8Base()) {
1261 if (Subtarget->hasNEON()) {
1268 if (Subtarget->hasFP64()) {
1283 if (Subtarget->hasFullFP16()) {
1289 ISD::FCOS, ISD::FSIN, ISD::FSINCOS,
1290 ISD::FSINCOSPI, ISD::FMODF, ISD::FACOS,
1291 ISD::FASIN, ISD::FATAN, ISD::FATAN2,
1292 ISD::FCOSH, ISD::FSINH, ISD::FTANH,
1293 ISD::FTAN, ISD::FEXP, ISD::FEXP2,
1294 ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
1310 for (
auto Op : {ISD::FROUND, ISD::FROUNDEVEN, ISD::FTRUNC,
1311 ISD::FNEARBYINT, ISD::FRINT, ISD::FFLOOR,
1320 if (Subtarget->hasNEON()) {
1332 if (Subtarget->hasV8Ops()) {
1347 if (Subtarget->hasFullFP16()) {
1375 if (TT.isOSWindows()) {
1392 if (Subtarget->hasMVEIntegerOps())
1395 if (Subtarget->hasV6Ops())
1397 if (Subtarget->isThumb1Only())
1400 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1401 Subtarget->isThumb2()) {
1407 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1408 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1430 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1436 return Subtarget->useSoftFloat();
1440 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1453std::pair<const TargetRegisterClass *, uint8_t>
1464 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1465 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1466 RRC = &ARM::DPRRegClass;
1471 if (Subtarget->useNEONForSinglePrecisionFP())
1474 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1475 case MVT::v4f32:
case MVT::v2f64:
1476 RRC = &ARM::DPRRegClass;
1480 RRC = &ARM::DPRRegClass;
1484 RRC = &ARM::DPRRegClass;
1488 return std::make_pair(RRC,
Cost);
1497 if ((Subtarget->hasMVEIntegerOps() &&
1498 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1499 VT == MVT::v16i8)) ||
1500 (Subtarget->hasMVEFloatOps() &&
1501 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1515 if (Subtarget->hasNEON()) {
1516 if (VT == MVT::v4i64)
1517 return &ARM::QQPRRegClass;
1518 if (VT == MVT::v8i64)
1519 return &ARM::QQQQPRRegClass;
1521 if (Subtarget->hasMVEIntegerOps()) {
1522 if (VT == MVT::v4i64)
1523 return &ARM::MQQPRRegClass;
1524 if (VT == MVT::v8i64)
1525 return &ARM::MQQQQPRRegClass;
1534 Align &PrefAlign)
const {
1541 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1553 unsigned NumVals =
N->getNumValues();
1557 for (
unsigned i = 0; i != NumVals; ++i) {
1558 EVT VT =
N->getValueType(i);
1559 if (VT == MVT::Glue || VT == MVT::Other)
1565 if (!
N->isMachineOpcode())
1573 if (
MCID.getNumDefs() == 0)
1575 if (!Itins->isEmpty() &&
1576 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1590 return Const->getZExtValue() == 16;
1598 return Const->getZExtValue() == 16;
1606 return Const->getZExtValue() == 16;
1675 bool isVarArg)
const {
1694 if (!
getTM().isAAPCS_ABI())
1696 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1704 if (!
getTM().isAAPCS_ABI()) {
1705 if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() && !isVarArg)
1708 }
else if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() &&
1717 bool isVarArg)
const {
1718 return CCAssignFnForNode(CC,
false, isVarArg);
1722 bool isVarArg)
const {
1723 return CCAssignFnForNode(CC,
true, isVarArg);
1730 bool isVarArg)
const {
1731 switch (getEffectiveCallingConv(CC, isVarArg)) {
1757 if (Subtarget->hasFullFP16()) {
1758 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1762 Val = DAG.
getNode(ISD::BITCAST, dl, ValVT, Val);
1770 if (Subtarget->hasFullFP16()) {
1771 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1774 Val = DAG.
getNode(ISD::BITCAST, dl,
1779 return DAG.
getNode(ISD::BITCAST, dl, LocVT, Val);
1784SDValue ARMTargetLowering::LowerCallResult(
1788 SDValue ThisVal,
bool isCmseNSCall)
const {
1796 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1797 CCValAssign VA = RVLocs[i];
1801 if (i == 0 && isThisReturn) {
1803 "unexpected return calling convention register assignment");
1821 if (!Subtarget->isLittle())
1823 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1838 if (!Subtarget->isLittle())
1840 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1881std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1883 bool IsTailCall,
int SPDiff)
const {
1885 MachinePointerInfo DstInfo;
1905 return std::make_pair(DstAddr, DstInfo);
1914ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1927 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1930 int SrcFI = SrcFrameIdxNode->getIndex();
1931 int DstFI = DstFrameIdxNode->getIndex();
1933 "byval passed in non-fixed stack slot");
1955 if (SrcOffset == DstOffset)
1963 RegsToPassVector &RegsToPass,
1970 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1971 unsigned id = Subtarget->isLittle() ? 0 : 1;
1983 MachinePointerInfo DstInfo;
1984 std::tie(DstAddr, DstInfo) =
1985 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2002 SelectionDAG &DAG = CLI.
DAG;
2004 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2005 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2006 SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2013 const CallBase *CB = CLI.
CB;
2016 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2018 MachineFunction::CallSiteInfo CSInfo;
2019 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2020 bool isThisReturn =
false;
2021 bool isCmseNSCall =
false;
2022 bool isSibCall =
false;
2023 bool PreferIndirect =
false;
2024 bool GuardWithBTI =
false;
2034 !Subtarget->noBTIAtReturnTwice())
2039 CSInfo = MachineFunction::CallSiteInfo(*CB);
2043 isCmseNSCall =
true;
2046 if (!Subtarget->supportsTailCall())
2062 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2063 count_if(GV->users(), [&BB](
const User *U) {
2064 return isa<Instruction>(U) &&
2065 cast<Instruction>(U)->getParent() == BB;
2072 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2086 "site marked musttail");
2089 unsigned NumBytes = CCInfo.getStackSize();
2098 if (isTailCall && !isSibCall) {
2099 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2100 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2105 assert(StackAlign &&
"data layout string is missing stack alignment");
2106 NumBytes =
alignTo(NumBytes, *StackAlign);
2111 SPDiff = NumReusableBytes - NumBytes;
2115 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2131 RegsToPassVector RegsToPass;
2140 DenseMap<unsigned, SDValue> ByValTemporaries;
2144 for (
const CCValAssign &VA : ArgLocs) {
2146 SDValue Src = OutVals[ArgIdx];
2147 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2149 if (!
Flags.isByVal())
2153 MachinePointerInfo DstInfo;
2154 std::tie(Dst, DstInfo) =
2155 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2156 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2158 if (Copy == NoCopy) {
2163 }
else if (Copy == CopyOnce) {
2167 ByValTemporaries[ArgIdx] = Src;
2169 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2173 int TempFrameIdx = MFI.CreateStackObject(
2174 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2182 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2183 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2185 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2186 ByValTemporaries[ArgIdx] = Temp;
2189 if (!ByValCopyChains.
empty())
2199 bool AfterFormalArgLoads =
false;
2203 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2205 ++i, ++realArgIdx) {
2206 CCValAssign &VA = ArgLocs[i];
2207 SDValue Arg = OutVals[realArgIdx];
2208 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2209 bool isByVal =
Flags.isByVal();
2229 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2231 if (ByValTempChain) {
2236 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2237 if (Outs[
I].
Flags.isByVal())
2245 FrameIndexSDNode *FIN =
2250 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2253 for (
const CCValAssign &VA : ArgLocs) {
2261 if (!IncomingLoad.
empty()) {
2269 AfterFormalArgLoads =
true;
2281 auto ArgVT = Outs[realArgIdx].ArgVT;
2282 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2300 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2301 StackPtr, MemOpChains, isTailCall, SPDiff);
2305 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2306 StackPtr, MemOpChains, isTailCall, SPDiff);
2310 MachinePointerInfo DstInfo;
2311 std::tie(DstAddr, DstInfo) =
2312 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2316 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2317 StackPtr, MemOpChains, isTailCall, SPDiff);
2319 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2320 Outs[0].VT == MVT::i32) {
2322 "unexpected calling convention register assignment");
2323 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2324 "unexpected use of 'returned'");
2325 isThisReturn =
true;
2330 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2331 }
else if (isByVal) {
2333 unsigned offset = 0;
2337 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2338 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2341 bool NeedsStackCopy;
2342 if (
auto It = ByValTemporaries.
find(realArgIdx);
2343 It != ByValTemporaries.
end()) {
2344 ByValSrc = It->second;
2345 NeedsStackCopy =
true;
2348 NeedsStackCopy = !isTailCall;
2352 if (CurByValIdx < ByValArgsCount) {
2353 unsigned RegBegin, RegEnd;
2354 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2358 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2362 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2365 RegsToPass.push_back(std::make_pair(j, Load));
2370 offset = RegEnd - RegBegin;
2372 CCInfo.nextInRegsParam();
2377 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2380 MachinePointerInfo DstInfo;
2381 std::tie(Dst, DstInfo) =
2382 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2390 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2391 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2398 MachinePointerInfo DstInfo;
2399 std::tie(DstAddr, DstInfo) =
2400 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2407 if (!MemOpChains.
empty())
2413 for (
const auto &[
Reg,
N] : RegsToPass) {
2421 bool isDirect =
false;
2424 const GlobalValue *GVal =
nullptr;
2426 GVal =
G->getGlobal();
2427 bool isStub = !TM.shouldAssumeDSOLocal(GVal) && Subtarget->isTargetMachO();
2429 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2430 bool isLocalARMFunc =
false;
2433 if (Subtarget->genLongCalls()) {
2435 "long-calls codegen is not position independent!");
2440 if (Subtarget->genExecuteOnly()) {
2441 if (Subtarget->useMovt())
2453 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2459 const char *Sym = S->getSymbol();
2461 if (Subtarget->genExecuteOnly()) {
2462 if (Subtarget->useMovt())
2474 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2481 if (!PreferIndirect) {
2486 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2488 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2489 assert(Subtarget->isTargetMachO() &&
"WrapperPIC use on non-MachO?");
2491 ARMISD::WrapperPIC, dl, PtrVt,
2498 }
else if (Subtarget->isTargetCOFF()) {
2499 assert(Subtarget->isTargetWindows() &&
2500 "Windows is the only supported COFF target");
2504 else if (!TM.shouldAssumeDSOLocal(GVal))
2511 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2520 const char *Sym = S->getSymbol();
2521 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2523 ARMConstantPoolValue *CPV =
2525 ARMPCLabelIndex, 4);
2527 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2532 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2539 assert(!isARMFunc && !isDirect &&
2540 "Cannot handle call to ARM function or direct call");
2544 "call to non-secure function would require "
2545 "passing arguments on stack",
2551 "call to non-secure function would return value through pointer",
2558 if (Subtarget->isThumb()) {
2560 CallOpc = ARMISD::t2CALL_BTI;
2561 else if (isCmseNSCall)
2562 CallOpc = ARMISD::tSECALL;
2563 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2564 CallOpc = ARMISD::CALL_NOLINK;
2566 CallOpc = ARMISD::CALL;
2568 if (!isDirect && !Subtarget->hasV5TOps())
2569 CallOpc = ARMISD::CALL_NOLINK;
2570 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2572 !Subtarget->hasMinSize())
2574 CallOpc = ARMISD::CALL_NOLINK;
2576 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2583 if (isTailCall && !isSibCall) {
2588 std::vector<SDValue>
Ops;
2589 Ops.push_back(Chain);
2590 Ops.push_back(Callee);
2598 for (
const auto &[
Reg,
N] : RegsToPass)
2602 const uint32_t *
Mask;
2603 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2611 isThisReturn =
false;
2617 assert(Mask &&
"Missing call preserved mask for calling convention");
2621 Ops.push_back(InGlue);
2634 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2645 uint64_t CalleePopBytes =
2648 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2654 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2655 InVals, isThisReturn,
2656 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2663void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2664 Align Alignment)
const {
2666 Alignment = std::max(Alignment,
Align(4));
2672 unsigned AlignInRegs = Alignment.
value() / 4;
2673 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2674 for (
unsigned i = 0; i < Waste; ++i)
2680 unsigned Excess = 4 * (ARM::R4 -
Reg);
2687 if (NSAAOffset != 0 &&
Size > Excess) {
2699 unsigned ByValRegBegin =
Reg;
2700 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2704 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2710 Size = std::max<int>(
Size - Excess, 0);
2718bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2724 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2725 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2726 const SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2727 const SelectionDAG &DAG = CLI.
DAG;
2732 assert(Subtarget->supportsTailCall());
2745 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2747 if (!(Subtarget->isThumb1Only() ||
2748 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2749 AddressRegisters.
insert(ARM::R12);
2750 for (
const CCValAssign &AL : ArgLocs)
2752 AddressRegisters.
erase(
AL.getLocReg());
2753 if (AddressRegisters.
empty()) {
2754 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2773 <<
" (guaranteed tail-call CC)\n");
2774 return CalleeCC == CallerCC;
2779 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2781 if (isCalleeStructRet != isCallerStructRet) {
2794 const GlobalValue *GV =
G->getGlobal();
2797 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2798 TT.isOSBinFormatMachO())) {
2807 getEffectiveCallingConv(CalleeCC, isVarArg),
2808 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
2815 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2816 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2817 if (CalleeCC != CallerCC) {
2818 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2819 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2828 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2838 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2857 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2866 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2879 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2882 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2886 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2891 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2913 bool isLittleEndian = Subtarget->isLittle();
2916 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2925 "secure entry function would return value through pointer",
2930 for (
unsigned i = 0, realRVLocIdx = 0;
2932 ++i, ++realRVLocIdx) {
2933 CCValAssign &VA = RVLocs[i];
2936 SDValue Arg = OutVals[realRVLocIdx];
2937 bool ReturnF16 =
false;
2939 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
2972 auto RetVT = Outs[realRVLocIdx].ArgVT;
2994 DAG.
getVTList(MVT::i32, MVT::i32), Half);
2998 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3004 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3016 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3018 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3023 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3033 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3059 !Subtarget->isMClass()) {
3060 if (Subtarget->isThumb1Only())
3067 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3070bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3071 if (
N->getNumValues() != 1)
3073 if (!
N->hasNUsesOfValue(1, 0))
3077 SDNode *
Copy = *
N->user_begin();
3081 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3083 TCChain =
Copy->getOperand(0);
3084 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3085 SDNode *VMov =
Copy;
3087 SmallPtrSet<SDNode*, 2>
Copies;
3088 for (SDNode *U : VMov->
users()) {
3096 for (SDNode *U : VMov->
users()) {
3097 SDValue UseChain =
U->getOperand(0);
3105 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3111 }
else if (
Copy->getOpcode() == ISD::BITCAST) {
3113 if (!
Copy->hasOneUse())
3120 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3122 TCChain =
Copy->getOperand(0);
3127 bool HasRet =
false;
3128 for (
const SDNode *U :
Copy->users()) {
3129 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3130 U->getOpcode() != ARMISD::INTRET_GLUE)
3142bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3143 if (!Subtarget->supportsTailCall())
3160 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3176 EVT PtrVT =
Op.getValueType();
3186 if (Subtarget->genExecuteOnly()) {
3188 auto *
T =
CP->getType();
3189 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3191 auto GV =
new GlobalVariable(
3199 return LowerGlobalAddress(GA, DAG);
3204 Align CPAlign =
CP->getAlign();
3205 if (Subtarget->isThumb1Only())
3206 CPAlign = std::max(CPAlign,
Align(4));
3207 if (
CP->isMachineConstantPoolEntry())
3212 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3219 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3228 unsigned ARMPCLabelIndex = 0;
3234 if (!IsPositionIndependent) {
3237 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3244 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3248 if (!IsPositionIndependent)
3251 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3279ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3281 assert(Subtarget->isTargetDarwin() &&
3282 "This function expects a Darwin target");
3287 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3293 MVT::i32,
DL, Chain, DescAddr,
3308 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3317 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3323ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3325 assert(Subtarget->isTargetWindows() &&
"Windows specific TLS lowering");
3349 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3357 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3358 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3364 MachinePointerInfo());
3371 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3384 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3386 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3388 ARMConstantPoolValue *CPV =
3399 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3406 TargetLowering::CallLoweringInfo CLI(DAG);
3411 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3412 return CallResult.first;
3421 const GlobalValue *GV = GA->
getGlobal();
3431 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3434 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3435 ARMConstantPoolValue *CPV =
3442 PtrVT, dl, Chain,
Offset,
3450 PtrVT, dl, Chain,
Offset,
3455 ARMConstantPoolValue *CPV =
3460 PtrVT, dl, Chain,
Offset,
3475 if (Subtarget->isTargetDarwin())
3476 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3478 if (Subtarget->isTargetWindows())
3479 return LowerGlobalTLSAddressWindows(
Op, DAG);
3482 assert(Subtarget->isTargetELF() &&
"Only ELF implemented here");
3488 return LowerToTLSGeneralDynamicModel(GA, DAG);
3491 return LowerToTLSExecModels(GA, DAG, model);
3500 while (!Worklist.
empty()) {
3508 if (!
I ||
I->getParent()->getParent() !=
F)
3537 if (!GVar || !GVar->hasInitializer() ||
3538 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3539 !GVar->hasLocalLinkage())
3544 auto *
Init = GVar->getInitializer();
3546 Init->needsDynamicRelocation())
3558 unsigned RequiredPadding = 4 - (
Size % 4);
3559 bool PaddingPossible =
3560 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3565 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3589 if (RequiredPadding != 4) {
3594 while (RequiredPadding--)
3606 ++NumConstpoolPromoted;
3607 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3612 if (!(GV = GA->getAliaseeObject()))
3615 return V->isConstant();
3624 return LowerGlobalAddressWindows(
Op, DAG);
3626 return LowerGlobalAddressELF(
Op, DAG);
3628 return LowerGlobalAddressDarwin(
Op, DAG);
3640 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3653 }
else if (Subtarget->isROPI() && IsRO) {
3658 }
else if (Subtarget->isRWPI() && !IsRO) {
3661 if (Subtarget->useMovt()) {
3664 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3666 ARMConstantPoolValue *CPV =
3669 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3683 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3684 if (Subtarget->useMovt())
3688 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3692 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3701 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3702 "ROPI/RWPI not currently supported for Darwin");
3707 if (Subtarget->useMovt())
3718 if (Subtarget->isGVIndirectSymbol(GV))
3726 assert(Subtarget->isTargetWindows() &&
"non-Windows COFF is not supported");
3727 assert(Subtarget->useMovt() &&
3728 "Windows on ARM expects to use movw/movt");
3729 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3730 "ROPI/RWPI not currently supported for Windows");
3737 else if (!TM.shouldAssumeDSOLocal(GV))
3760 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3761 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3762 Op.getOperand(1), Val);
3768 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3775 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3779SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3782 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3786 case Intrinsic::arm_gnu_eabi_mcount: {
3792 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3793 const uint32_t *
Mask =
3795 assert(Mask &&
"Missing call preserved mask for calling convention");
3800 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3804 if (Subtarget->isThumb())
3807 ARM::tBL_PUSHLR, dl, ResultTys,
3808 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3809 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3813 {ReturnAddress, Callee, RegisterMask, Chain}),
3822 unsigned IntNo =
Op.getConstantOperandVal(0);
3826 case Intrinsic::thread_pointer: {
3828 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3830 case Intrinsic::arm_cls: {
3831 const SDValue &Operand =
Op.getOperand(1);
3832 const EVT VTy =
Op.getValueType();
3843 case Intrinsic::arm_cls64: {
3846 const SDValue &Operand =
Op.getOperand(1);
3847 const EVT VTy =
Op.getValueType();
3870 case Intrinsic::eh_sjlj_lsda: {
3872 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3877 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3878 ARMConstantPoolValue *CPV =
3882 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3887 if (IsPositionIndependent) {
3889 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3893 case Intrinsic::arm_neon_vabs:
3896 case Intrinsic::arm_neon_vabds:
3897 if (
Op.getValueType().isInteger())
3899 Op.getOperand(1),
Op.getOperand(2));
3901 case Intrinsic::arm_neon_vabdu:
3903 Op.getOperand(1),
Op.getOperand(2));
3904 case Intrinsic::arm_neon_vmulls:
3905 case Intrinsic::arm_neon_vmullu: {
3906 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3907 ? ARMISD::VMULLs : ARMISD::VMULLu;
3908 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3909 Op.getOperand(1),
Op.getOperand(2));
3911 case Intrinsic::arm_neon_vminnm:
3912 case Intrinsic::arm_neon_vmaxnm: {
3913 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3914 ? ISD::FMINNUM : ISD::FMAXNUM;
3915 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3916 Op.getOperand(1),
Op.getOperand(2));
3918 case Intrinsic::arm_neon_vminu:
3919 case Intrinsic::arm_neon_vmaxu: {
3920 if (
Op.getValueType().isFloatingPoint())
3922 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3924 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3925 Op.getOperand(1),
Op.getOperand(2));
3927 case Intrinsic::arm_neon_vmins:
3928 case Intrinsic::arm_neon_vmaxs: {
3930 if (!
Op.getValueType().isFloatingPoint()) {
3931 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3933 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3934 Op.getOperand(1),
Op.getOperand(2));
3936 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3937 ? ISD::FMINIMUM : ISD::FMAXIMUM;
3938 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3939 Op.getOperand(1),
Op.getOperand(2));
3941 case Intrinsic::arm_neon_vtbl1:
3942 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
3943 Op.getOperand(1),
Op.getOperand(2));
3944 case Intrinsic::arm_neon_vtbl2:
3945 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
3946 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3947 case Intrinsic::arm_mve_pred_i2v:
3948 case Intrinsic::arm_mve_pred_v2i:
3949 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
3951 case Intrinsic::arm_mve_vreinterpretq:
3952 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
3954 case Intrinsic::arm_mve_lsll:
3955 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
3956 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3957 case Intrinsic::arm_mve_asrl:
3958 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
3959 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3970 if (!Subtarget->hasDataBarrier()) {
3974 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
3975 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
3976 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
3986 }
else if (Subtarget->preferISHSTBarriers() &&
3995 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4003 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4005 return Op.getOperand(0);
4008 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4010 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4012 return Op.getOperand(0);
4014 unsigned isData =
Op.getConstantOperandVal(4);
4015 if (Subtarget->isThumb()) {
4017 isRead = ~isRead & 1;
4018 isData = ~isData & 1;
4021 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4036 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4044 const SDLoc &dl)
const {
4046 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4048 const TargetRegisterClass *RC;
4050 RC = &ARM::tGPRRegClass;
4052 RC = &ARM::GPRRegClass;
4066 MVT::i32, dl, Root, FIN,
4072 if (!Subtarget->isLittle())
4074 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4087 const Value *OrigArg,
4088 unsigned InRegsParamRecordIdx,
4089 int ArgOffset,
unsigned ArgSize)
const {
4103 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4104 unsigned RBegin, REnd;
4109 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4114 ArgOffset = -4 * (ARM::R4 - RBegin);
4121 const TargetRegisterClass *RC =
4124 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4128 MachinePointerInfo(OrigArg, 4 * i));
4133 if (!MemOps.
empty())
4142 unsigned TotalArgRegsSaveSize,
4143 bool ForceMutable)
const {
4145 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4154 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4158bool ARMTargetLowering::splitValueIntoRegisterParts(
4160 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4162 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4167 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
4174SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4176 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4177 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4184 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
4190SDValue ARMTargetLowering::LowerFormalArguments(
4197 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4206 unsigned CurArgIdx = 0;
4218 unsigned ArgRegBegin = ARM::R4;
4219 for (
const CCValAssign &VA : ArgLocs) {
4225 if (!
Flags.isByVal())
4229 unsigned RBegin, REnd;
4231 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4237 int lastInsIndex = -1;
4241 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4244 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4248 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4249 CCValAssign &VA = ArgLocs[i];
4250 if (Ins[VA.
getValNo()].isOrigArg()) {
4251 std::advance(CurOrigArg,
4252 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4264 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4271 MVT::f64, dl, Chain, FIN,
4274 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4282 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4284 const TargetRegisterClass *RC;
4286 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4287 RC = &ARM::HPRRegClass;
4288 else if (RegVT == MVT::f32)
4289 RC = &ARM::SPRRegClass;
4290 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4291 RegVT == MVT::v4bf16)
4292 RC = &ARM::DPRRegClass;
4293 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4294 RegVT == MVT::v8bf16)
4295 RC = &ARM::QPRRegClass;
4296 else if (RegVT == MVT::i32)
4298 : &ARM::GPRRegClass;
4344 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4350 if (index != lastInsIndex)
4352 ISD::ArgFlagsTy
Flags =
Ins[index].Flags;
4358 if (
Flags.isByVal()) {
4359 assert(Ins[index].isOrigArg() &&
4360 "Byval arguments cannot be implicit");
4364 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4398 lastInsIndex = index;
4405 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4406 TotalArgRegsSaveSize);
4410 "secure entry function must not be variadic", dl.
getDebugLoc()));
4420 assert(StackAlign &&
"data layout string is missing stack alignment");
4421 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4430 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4439 return CFP->getValueAPF().isPosZero();
4442 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4443 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4446 return CFP->getValueAPF().isPosZero();
4448 }
else if (
Op->getOpcode() == ISD::BITCAST &&
4449 Op->getValueType(0) == MVT::f64) {
4453 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4464 const SDLoc &dl)
const {
4466 unsigned C = RHSC->getZExtValue();
4530 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4534 unsigned Mask =
LHS.getConstantOperandVal(1);
4536 uint64_t RHSV = RHSC->getZExtValue();
4537 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4539 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4553 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4556 LHS.getConstantOperandVal(1) < 31) {
4557 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4582 unsigned CompareType;
4585 CompareType = ARMISD::CMP;
4590 CompareType = ARMISD::CMPZ;
4600 bool Signaling)
const {
4601 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4607 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4616std::pair<SDValue, SDValue>
4619 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4631 switch (
Op.getOpcode()) {
4683 return std::make_pair(
Value, OverflowCmp);
4694 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4699 EVT VT =
Op.getValueType();
4702 DAG.
getNode(ARMISD::CMOV, dl, VT, TVal, FVal, ARMcc, OverflowCmp);
4704 SDVTList VTs = DAG.
getVTList(
Op.getValueType(), MVT::i32);
4742 EVT VT =
Op.getValueType();
4743 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4746 switch (
Op.getOpcode()) {
4771 EVT VT =
Op.getValueType();
4772 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4782 switch (
Op->getOpcode()) {
4784 NewOpcode = ARMISD::UQADD8b;
4787 NewOpcode = ARMISD::QADD8b;
4790 NewOpcode = ARMISD::UQSUB8b;
4793 NewOpcode = ARMISD::QSUB8b;
4798 switch (
Op->getOpcode()) {
4800 NewOpcode = ARMISD::UQADD16b;
4803 NewOpcode = ARMISD::QADD16b;
4806 NewOpcode = ARMISD::UQSUB16b;
4809 NewOpcode = ARMISD::QSUB16b;
4817 DAG.
getNode(NewOpcode, dl, MVT::i32,
4828 unsigned Opc =
Cond.getOpcode();
4830 if (
Cond.getResNo() == 1 &&
4838 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4839 EVT VT =
Op.getValueType();
4841 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4849 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4850 const ConstantSDNode *CMOVTrue =
4852 const ConstantSDNode *CMOVFalse =
4855 if (CMOVTrue && CMOVFalse) {
4861 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
4863 False = SelectFalse;
4864 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
4870 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
4871 Cond.getOperand(3), DAG);
4886 bool &swpCmpOps,
bool &swpVselOps) {
4914 swpCmpOps = !swpCmpOps;
4915 swpVselOps = !swpVselOps;
4938 if (!Subtarget->hasFP64() && VT == MVT::f64) {
4940 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
4942 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
4956 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
4977 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
4979 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5000 EVT VT =
Op.getValueType();
5022 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5035 int64_t PosVal = std::max(Val1, Val2);
5036 int64_t NegVal = std::min(Val1, Val2);
5048 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5051 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5083 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5088 if (*K != KTmp || V != VTmp)
5099bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5101 return !Subtarget->hasVFP2Base();
5103 return !Subtarget->hasFP64();
5105 return !Subtarget->hasFullFP16();
5110 EVT VT =
Op.getValueType();
5114 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5126 if (VT == MVT::i32 &&
5146 if (
Op.getValueType().isInteger()) {
5154 LHS.getValueType() ==
RHS.getValueType()) {
5155 EVT VT =
LHS.getValueType();
5161 Shift = DAG.
getNOT(dl, Shift, VT);
5167 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5168 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5171 unsigned Opcode = 0;
5173 if (TVal == ~FVal) {
5174 Opcode = ARMISD::CSINV;
5175 }
else if (TVal == ~FVal + 1) {
5176 Opcode = ARMISD::CSNEG;
5177 }
else if (TVal + 1 == FVal) {
5178 Opcode = ARMISD::CSINC;
5179 }
else if (TVal == FVal + 1) {
5180 Opcode = ARMISD::CSINC;
5189 if (Opcode != ARMISD::CSINC &&
5199 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5210 EVT VT =
TrueVal.getValueType();
5211 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5215 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5220 if (!
RHS.getNode()) {
5226 if (
LHS.getValueType() == MVT::i32) {
5237 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5238 TrueVal.getValueType() == MVT::f32 ||
5239 TrueVal.getValueType() == MVT::f64)) {
5253 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5263 if (Subtarget->hasFPARMv8Base() &&
5265 (
TrueVal.getValueType() == MVT::f16 ||
5266 TrueVal.getValueType() == MVT::f32 ||
5267 TrueVal.getValueType() == MVT::f64)) {
5268 bool swpCmpOps =
false;
5269 bool swpVselOps =
false;
5283 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5286 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5296 if (!
N->hasOneUse())
5299 if (!
N->getNumValues())
5301 EVT VT =
Op.getValueType();
5302 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5319 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5320 Ld->getPointerInfo(), Ld->getAlign(),
5321 Ld->getMemOperand()->getFlags());
5337 SDValue Ptr = Ld->getBasePtr();
5339 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5340 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5345 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5346 Ld->getPointerInfo().getWithOffset(4),
5348 Ld->getMemOperand()->getFlags());
5366 bool LHSSeenZero =
false;
5368 bool RHSSeenZero =
false;
5370 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5381 if (
LHS.getValueType() == MVT::f32) {
5387 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5399 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5400 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5415 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5427 unsigned Opc =
Cond.getOpcode();
5429 !Subtarget->isThumb1Only();
5430 if (
Cond.getResNo() == 1 &&
5440 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5446 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5448 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5463 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5468 if (!
RHS.getNode()) {
5476 unsigned Opc =
LHS.getOpcode();
5478 !Subtarget->isThumb1Only();
5490 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5497 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5500 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5504 if (
LHS.getValueType() == MVT::i32) {
5507 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5510 SDNodeFlags
Flags =
Op->getFlags();
5511 if (
Flags.hasNoNaNs() &&
5516 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5530 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5544 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5547 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5552 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5553 Addr,
Op.getOperand(2), JTI);
5557 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5561 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5564 DAG.
getLoad(PTy, dl, Chain, Addr,
5567 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5572 EVT VT =
Op.getValueType();
5575 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5576 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5584 const EVT OpTy =
Op.getOperand(0).getValueType();
5585 if (OpTy == MVT::v4f32)
5587 else if (OpTy == MVT::v4f16 && HasFullFP16)
5589 else if (OpTy == MVT::v8f16 && HasFullFP16)
5594 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5597 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5602 EVT VT =
Op.getValueType();
5606 bool IsStrict =
Op->isStrictFPOpcode();
5607 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5609 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5622 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5623 CallOptions, Loc, Chain);
5633 Loc,
Op.getValueType(), SrcVal);
5642 EVT VT =
Op.getValueType();
5644 EVT FromVT =
Op.getOperand(0).getValueType();
5646 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5648 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5649 Subtarget->hasFP64())
5651 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5652 Subtarget->hasFullFP16())
5654 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5655 Subtarget->hasMVEFloatOps())
5657 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5658 Subtarget->hasMVEFloatOps())
5661 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5678 EVT VT =
Op.getValueType();
5681 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5687 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5688 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5689 "Invalid type for custom lowering!");
5694 if (VT == MVT::v4f32)
5695 DestVecType = MVT::v4i32;
5696 else if (VT == MVT::v4f16 && HasFullFP16)
5697 DestVecType = MVT::v4i16;
5698 else if (VT == MVT::v8f16 && HasFullFP16)
5699 DestVecType = MVT::v8i16;
5705 switch (
Op.getOpcode()) {
5717 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5722 EVT VT =
Op.getValueType();
5725 if (isUnsupportedFloatingType(VT)) {
5735 CallOptions, SDLoc(
Op)).first;
5746 EVT VT =
Op.getValueType();
5748 bool InGPR = Tmp0.
getOpcode() == ISD::BITCAST ||
5750 bool UseNEON = !InGPR && Subtarget->hasNEON();
5757 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5760 DAG.
getNode(ISD::BITCAST, dl, OpVT, Mask),
5764 if (SrcVT == MVT::f32) {
5767 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5768 DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1),
5770 }
else if (VT == MVT::f32)
5771 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5772 DAG.
getNode(ISD::BITCAST, dl, MVT::v1i64, Tmp1),
5774 Tmp0 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp0);
5775 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1);
5786 if (VT == MVT::f32) {
5787 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::v2f32, Res);
5791 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Res);
5798 if (SrcVT == MVT::f64)
5801 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp1);
5807 if (VT == MVT::f32) {
5809 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
5810 return DAG.
getNode(ISD::BITCAST, dl, MVT::f32,
5820 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5828 EVT VT =
Op.getValueType();
5830 unsigned Depth =
Op.getConstantOperandVal(0);
5832 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5836 MachinePointerInfo());
5845 const ARMBaseRegisterInfo &ARI =
5846 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
5851 EVT VT =
Op.getValueType();
5853 unsigned Depth =
Op.getConstantOperandVal(0);
5858 MachinePointerInfo());
5866 return StringSwitch<Register>(
RegName)
5867 .Case(
"sp", ARM::SP)
5878 assert(
N->getValueType(0) == MVT::i64
5879 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
5882 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
5922 const APInt &APIntIndex = Index->getAPIntValue();
5924 NewIndex *= APIntIndex;
5936 SDValue BitCast = DAG.
getNode(ISD::BITCAST, dl, VecVT, ExtractSrc);
5953 EVT SrcVT =
Op.getValueType();
5954 EVT DstVT =
N->getValueType(0);
5956 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
5957 (DstVT == MVT::f16 || DstVT == MVT::bf16))
5958 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
5961 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
5962 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
5963 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
5970 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
5981 return DAG.
getNode(ISD::BITCAST, dl, DstVT,
5982 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
5990 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
5992 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
5994 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6014 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6015 return DAG.
getNode(ISD::BITCAST, dl, VT, Vmov);
6023 EVT VT =
Op.getValueType();
6045 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6055 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6066 EVT VT =
Op.getValueType();
6087 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6108 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6160 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6188 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6218 EVT VT =
N->getValueType(0);
6219 if (VT.
isVector() && ST->hasNEON()) {
6228 if (ElemTy == MVT::i8) {
6236 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6239 unsigned NumBits = ElemTy.getSizeInBits();
6241 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6251 if (ElemTy == MVT::i64) {
6264 if (!ST->hasV6T2Ops())
6273 EVT VT =
N->getValueType(0);
6276 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6277 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6278 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6279 "Unexpected type for custom ctpop lowering");
6287 unsigned EltSize = 8;
6309 while (
Op.getOpcode() == ISD::BITCAST)
6310 Op =
Op.getOperand(0);
6312 APInt SplatBits, SplatUndef;
6313 unsigned SplatBitSize;
6316 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6318 SplatBitSize > ElementBits)
6329 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6333 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6344 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6349 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6350 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6359 EVT VT =
N->getValueType(0);
6374 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6376 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6381 "unexpected vector shift opcode");
6383 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6384 unsigned VShiftOpc =
6385 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6386 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6392 EVT ShiftVT =
N->getOperand(1).getValueType();
6395 unsigned VShiftOpc =
6396 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6397 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6402 EVT VT =
N->getValueType(0);
6411 "Unknown shift to lower!");
6413 unsigned ShOpc =
N->getOpcode();
6414 if (ST->hasMVEIntegerOps()) {
6416 unsigned ShPartsOpc = ARMISD::LSLL;
6437 ShPartsOpc = ARMISD::LSRL;
6439 ShPartsOpc = ARMISD::ASRL;
6444 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6458 if (ST->isThumb1Only())
6463 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6467 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6471 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6479 bool Invert =
false;
6486 EVT VT =
Op.getValueType();
6494 assert(ST->hasMVEIntegerOps() &&
6495 "No hardware support for integer vector comparison!");
6497 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6518 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6520 Merged = DAG.
getNode(ISD::BITCAST, dl, CmpVT, Merged);
6522 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6532 switch (SetCCOpcode) {
6536 if (ST->hasMVEFloatOps()) {
6539 Invert =
true; [[fallthrough]];
6544 case ISD::SETLT: Swap =
true; [[fallthrough]];
6548 case ISD::SETLE: Swap =
true; [[fallthrough]];
6564 Result = DAG.
getNOT(dl, Result, VT);
6567 case ISD::SETUO: Invert =
true; [[fallthrough]];
6576 Result = DAG.
getNOT(dl, Result, VT);
6582 switch (SetCCOpcode) {
6585 if (ST->hasMVEIntegerOps()) {
6588 Invert =
true; [[fallthrough]];
6591 case ISD::SETLT: Swap =
true; [[fallthrough]];
6593 case ISD::SETLE: Swap =
true; [[fallthrough]];
6610 if (AndOp.getNode() && AndOp.getOpcode() == ISD::BITCAST)
6613 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6614 Op0 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(0));
6615 Op1 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(1));
6618 Result = DAG.
getNOT(dl, Result, VT);
6643 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6646 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6652 Result = DAG.
getNOT(dl, Result, VT);
6664 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6680 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6691 unsigned OpCmode, Imm;
6702 switch (SplatBitSize) {
6707 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6710 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6715 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6716 if ((SplatBits & ~0xff) == 0) {
6722 if ((SplatBits & ~0xff00) == 0) {
6725 Imm = SplatBits >> 8;
6735 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6736 if ((SplatBits & ~0xff) == 0) {
6742 if ((SplatBits & ~0xff00) == 0) {
6745 Imm = SplatBits >> 8;
6748 if ((SplatBits & ~0xff0000) == 0) {
6751 Imm = SplatBits >> 16;
6754 if ((SplatBits & ~0xff000000) == 0) {
6757 Imm = SplatBits >> 24;
6764 if ((SplatBits & ~0xffff) == 0 &&
6765 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6768 Imm = SplatBits >> 8;
6776 if ((SplatBits & ~0xffffff) == 0 &&
6777 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6780 Imm = SplatBits >> 16;
6796 unsigned ImmMask = 1;
6798 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6799 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6801 }
else if ((SplatBits & BitMask) != 0) {
6810 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6824 EVT VT =
Op.getValueType();
6825 bool IsDouble = (VT == MVT::f64);
6831 if (
ST->genExecuteOnly()) {
6833 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6834 "Unexpected architecture");
6852 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
6857 if (!
ST->hasVFP3Base())
6862 if (IsDouble && !Subtarget->hasFP64())
6869 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
6887 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
6896 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
6907 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
6924 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
6950 unsigned ExpectedElt = Imm;
6951 for (
unsigned i = 1; i < NumElts; ++i) {
6955 if (ExpectedElt == NumElts)
6958 if (M[i] < 0)
continue;
6959 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
6967 bool &ReverseVEXT,
unsigned &Imm) {
6969 ReverseVEXT =
false;
6980 unsigned ExpectedElt = Imm;
6981 for (
unsigned i = 1; i < NumElts; ++i) {
6985 if (ExpectedElt == NumElts * 2) {
6990 if (M[i] < 0)
continue;
6991 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7006 return VT == MVT::v8i8 && M.size() == 8;
7011 if (Mask.size() == Elements * 2)
7012 return Index / Elements;
7013 return Mask[Index] == 0 ? 0 : 1;
7043 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7051 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7053 for (
unsigned j = 0; j < NumElts; j += 2) {
7054 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7055 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7060 if (M.size() == NumElts*2)
7075 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7078 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7080 for (
unsigned j = 0; j < NumElts; j += 2) {
7081 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7082 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7087 if (M.size() == NumElts*2)
7107 if (M.size() != NumElts && M.size() != NumElts*2)
7110 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7112 for (
unsigned j = 0; j < NumElts; ++j) {
7113 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7118 if (M.size() == NumElts*2)
7137 if (M.size() != NumElts && M.size() != NumElts*2)
7140 unsigned Half = NumElts / 2;
7141 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7143 for (
unsigned j = 0; j < NumElts; j += Half) {
7144 unsigned Idx = WhichResult;
7145 for (
unsigned k = 0; k < Half; ++k) {
7146 int MIdx = M[i + j + k];
7147 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7154 if (M.size() == NumElts*2)
7178 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7181 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7183 unsigned Idx = WhichResult * NumElts / 2;
7184 for (
unsigned j = 0; j < NumElts; j += 2) {
7185 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7186 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7192 if (M.size() == NumElts*2)
7211 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7214 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7216 unsigned Idx = WhichResult * NumElts / 2;
7217 for (
unsigned j = 0; j < NumElts; j += 2) {
7218 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7219 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7225 if (M.size() == NumElts*2)
7238 unsigned &WhichResult,
7241 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7242 return ARMISD::VTRN;
7243 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7244 return ARMISD::VUZP;
7245 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7246 return ARMISD::VZIP;
7250 return ARMISD::VTRN;
7252 return ARMISD::VUZP;
7254 return ARMISD::VZIP;
7263 if (NumElts != M.size())
7267 for (
unsigned i = 0; i != NumElts; ++i)
7268 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7277 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7285 int Ofs = Top ? 1 : 0;
7286 int Upper = SingleSource ? 0 : NumElts;
7287 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7288 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7290 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7299 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7308 unsigned Offset = Top ? 0 : 1;
7309 unsigned N = SingleSource ? 0 : NumElts;
7310 for (
unsigned i = 0; i < NumElts; i += 2) {
7311 if (M[i] >= 0 && M[i] != (
int)i)
7313 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7322 if (NumElts != M.size())
7330 unsigned Off0 = rev ? NumElts / 2 : 0;
7331 unsigned Off1 = rev ? 0 : NumElts / 2;
7332 for (
unsigned i = 0; i < NumElts; i += 2) {
7333 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7335 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7351 if (!ST->hasMVEFloatOps())
7356 if (VT != MVT::v8f16)
7377 for (
unsigned i = 1; i < 4; i++) {
7392 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7404 if (!ST->hasMVEFloatOps())
7409 if (VT != MVT::v4f32)
7425 for (
unsigned i = 1; i < 4; i++) {
7427 return Trunc.
getOpcode() == ISD::FP_EXTEND &&
7436 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7448 Val =
N->getAsZExtVal();
7450 if (ST->isThumb1Only()) {
7451 if (Val <= 255 || ~Val <= 255)
7463 EVT VT =
Op.getValueType();
7465 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7469 unsigned BitsPerBool;
7473 }
else if (NumElts == 4) {
7476 }
else if (NumElts == 8) {
7479 }
else if (NumElts == 16) {
7490 return U.get().isUndef() || U.get() == FirstOp;
7494 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7498 unsigned Bits32 = 0;
7499 for (
unsigned i = 0; i < NumElts; ++i) {
7503 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7505 Bits32 |= BoolMask << (i * BitsPerBool);
7511 for (
unsigned i = 0; i < NumElts; ++i) {
7524 if (!ST->hasMVEIntegerOps())
7528 EVT VT =
Op.getValueType();
7538 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7542 for (
unsigned I = 2;
I < NumElts;
I++) {
7558 switch (
N->getOpcode()) {
7569 return N->getOperand(1).getNode() ==
Op;
7571 switch (
N->getConstantOperandVal(0)) {
7572 case Intrinsic::arm_mve_add_predicated:
7573 case Intrinsic::arm_mve_mul_predicated:
7574 case Intrinsic::arm_mve_qadd_predicated:
7575 case Intrinsic::arm_mve_vhadd:
7576 case Intrinsic::arm_mve_hadd_predicated:
7577 case Intrinsic::arm_mve_vqdmulh:
7578 case Intrinsic::arm_mve_qdmulh_predicated:
7579 case Intrinsic::arm_mve_vqrdmulh:
7580 case Intrinsic::arm_mve_qrdmulh_predicated:
7581 case Intrinsic::arm_mve_vqdmull:
7582 case Intrinsic::arm_mve_vqdmull_predicated:
7584 case Intrinsic::arm_mve_sub_predicated:
7585 case Intrinsic::arm_mve_qsub_predicated:
7586 case Intrinsic::arm_mve_vhsub:
7587 case Intrinsic::arm_mve_hsub_predicated:
7588 return N->getOperand(2).getNode() ==
Op;
7603 EVT VT =
Op.getValueType();
7611 APInt SplatBits, SplatUndef;
7612 unsigned SplatBitSize;
7614 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7621 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7623 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7624 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7625 : SplatBitSize == 16 ? MVT::v8i16
7629 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7632 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7633 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7638 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7642 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7646 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7648 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7652 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7656 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7660 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7666 if (
ST->hasMVEIntegerOps() &&
7667 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7668 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7669 : SplatBitSize == 16 ? MVT::v8i16
7673 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7686 bool isOnlyLowElement =
true;
7687 bool usesOnlyOneValue =
true;
7688 bool hasDominantValue =
false;
7693 DenseMap<SDValue, unsigned> ValueCounts;
7695 for (
unsigned i = 0; i < NumElts; ++i) {
7700 isOnlyLowElement =
false;
7704 unsigned &
Count = ValueCounts[
V];
7707 if (++
Count > (NumElts / 2)) {
7708 hasDominantValue =
true;
7712 if (ValueCounts.
size() != 1)
7713 usesOnlyOneValue =
false;
7714 if (!
Value.getNode() && !ValueCounts.
empty())
7717 if (ValueCounts.
empty())
7729 if (hasDominantValue && EltSize <= 32) {
7738 ConstantSDNode *constIndex;
7745 if (VT !=
Value->getOperand(0).getValueType()) {
7748 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7753 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7758 if (!usesOnlyOneValue) {
7761 for (
unsigned I = 0;
I < NumElts; ++
I) {
7766 Ops.push_back(
Op.getOperand(
I));
7776 assert(FVT == MVT::f32 || FVT == MVT::f16);
7777 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7778 for (
unsigned i = 0; i < NumElts; ++i)
7779 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, IVT,
7783 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7785 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
7787 if (usesOnlyOneValue) {
7790 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7814 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7834 if (EltSize >= 32) {
7840 for (
unsigned i = 0; i < NumElts; ++i)
7841 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, EltVT,
Op.getOperand(i)));
7843 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
7854 for (
unsigned i = 0 ; i < NumElts; ++i) {
7873 EVT VT =
Op.getValueType();
7876 struct ShuffleSourceInfo {
7878 unsigned MinElt = std::numeric_limits<unsigned>::max();
7879 unsigned MaxElt = 0;
7889 int WindowScale = 1;
7891 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7899 for (
unsigned i = 0; i < NumElts; ++i) {
7914 SDValue SourceVec =
V.getOperand(0);
7916 if (Source == Sources.
end())
7920 unsigned EltNo =
V.getConstantOperandVal(1);
7927 if (Sources.
size() > 2)
7933 for (
auto &Source : Sources) {
7934 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
7935 if (SrcEltTy.
bitsLT(SmallestEltTy))
7936 SmallestEltTy = SrcEltTy;
7938 unsigned ResMultiplier =
7946 for (
auto &Src : Sources) {
7947 EVT SrcVT = Src.ShuffleVec.getValueType();
7951 if (SrcVTSize == VTSize)
7960 if (SrcVTSize < VTSize) {
7961 if (2 * SrcVTSize != VTSize)
7967 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
7971 if (SrcVTSize != 2 * VTSize)
7974 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
7979 if (Src.MinElt >= NumSrcElts) {
7984 Src.WindowBase = -NumSrcElts;
7985 }
else if (Src.MaxElt < NumSrcElts) {
7999 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8002 Src.WindowBase = -Src.MinElt;
8009 for (
auto &Src : Sources) {
8010 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8011 if (SrcEltTy == SmallestEltTy)
8014 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8016 Src.WindowBase *= Src.WindowScale;
8021 for (
auto Src : Sources)
8022 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8030 if (
Entry.isUndef())
8039 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8042 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8046 int *LaneMask = &
Mask[i * ResMultiplier];
8048 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8049 ExtractBase += NumElts * (Src - Sources.begin());
8050 for (
int j = 0;
j < LanesDefined; ++
j)
8051 LaneMask[j] = ExtractBase + j;
8057 assert(Sources.size() <= 2 &&
"Too many sources!");
8060 for (
unsigned i = 0; i < Sources.size(); ++i)
8067 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8089 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8109 unsigned PFIndexes[4];
8110 for (
unsigned i = 0; i != 4; ++i) {
8114 PFIndexes[i] = M[i];
8118 unsigned PFTableIndex =
8119 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8121 unsigned Cost = (PFEntry >> 30);
8127 bool ReverseVEXT, isV_UNDEF;
8128 unsigned Imm, WhichResult;
8131 if (EltSize >= 32 ||
8138 else if (Subtarget->hasNEON() &&
8143 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8146 else if (Subtarget->hasMVEIntegerOps() &&
8150 else if (Subtarget->hasMVEIntegerOps() &&
8164 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8165 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8166 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8169 if (LHSID == (1*9+2)*9+3)
return LHS;
8170 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8184 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8187 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8190 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8195 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8200 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8227 for (
int I : ShuffleMask)
8231 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8, V1,
8234 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8, V1, V2,
8240 EVT VT =
Op.getValueType();
8242 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8243 "Expect an v8i16/v16i8 type");
8249 std::vector<int> NewMask;
8253 NewMask.push_back(i);
8283 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8293 if (VT != MVT::v16i1)
8294 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8304 return DAG.
getNode(ISD::BITCAST, dl, NewVT, PredAsVector);
8309 EVT VT =
Op.getValueType();
8313 assert(ST->hasMVEIntegerOps() &&
8314 "No support for vector shuffle of boolean predicates");
8324 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8340 "Expected identical vector type in expanded i1 shuffle!");
8344 PredAsVector2, ShuffleMask);
8349 if (VT == MVT::v2i1) {
8350 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8353 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8355 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8366 EVT VT =
Op.getValueType();
8370 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8371 "Unexpected vector type");
8373 int QuarterSize = NumElts / 4;
8382 for (
int i = 0; i <
Length; i++) {
8383 if (ShuffleMask[Start + i] >= 0) {
8384 if (ShuffleMask[Start + i] %
Length != i)
8386 MovIdx = ShuffleMask[Start + i] /
Length;
8394 for (
int i = 1; i <
Length; i++) {
8395 if (ShuffleMask[Start + i] >= 0 &&
8396 (ShuffleMask[Start + i] /
Length != MovIdx ||
8397 ShuffleMask[Start + i] %
Length != i))
8403 for (
int Part = 0; Part < 4; ++Part) {
8405 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8419 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8424 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8426 for (
int Part = 0; Part < 4; ++Part)
8427 for (
int i = 0; i < QuarterSize; i++)
8429 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8431 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8434 for (
int Part = 0; Part < 4; ++Part)
8450 EVT VT =
Op.getValueType();
8462 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8466 if (Mask[i] != i + BaseOffset) {
8467 if (OffElement == -1)
8473 return NonUndef > 2 && OffElement != -1;
8477 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8479 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8490 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8501 EVT VT =
Op.getValueType();
8505 if (ST->hasMVEIntegerOps() && EltSize == 1)
8516 if (EltSize <= 32) {
8520 if (Lane == -1) Lane = 0;
8531 bool IsScalarToVector =
true;
8534 IsScalarToVector =
false;
8537 if (IsScalarToVector)
8540 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT, V1,
8544 bool ReverseVEXT =
false;
8546 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8549 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V2,
8554 return DAG.
getNode(ARMISD::VREV64, dl, VT, V1);
8556 return DAG.
getNode(ARMISD::VREV32, dl, VT, V1);
8558 return DAG.
getNode(ARMISD::VREV16, dl, VT, V1);
8561 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V1,
8570 unsigned WhichResult = 0;
8571 bool isV_UNDEF =
false;
8572 if (ST->hasNEON()) {
8574 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8581 if (ST->hasMVEIntegerOps()) {
8583 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2, V1,
8586 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V2,
8589 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V1,
8616 }) &&
"Unexpected shuffle index into UNDEF operand!");
8619 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8622 assert((WhichResult == 0) &&
8623 "In-place shuffle of concat can only have one result!");
8632 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8636 for (
bool Top : {
false,
true}) {
8637 for (
bool SingleSource : {
false,
true}) {
8638 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8643 SingleSource ? V1 : V2);
8659 unsigned PFIndexes[4];
8660 for (
unsigned i = 0; i != 4; ++i) {
8661 if (ShuffleMask[i] < 0)
8664 PFIndexes[i] = ShuffleMask[i];
8668 unsigned PFTableIndex =
8669 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8671 unsigned Cost = (PFEntry >> 30);
8677 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8678 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8688 if (EltSize >= 32) {
8693 V1 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V1);
8694 V2 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V2);
8696 for (
unsigned i = 0; i < NumElts; ++i) {
8697 if (ShuffleMask[i] < 0)
8701 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8706 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8709 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8713 if (ST->hasNEON() && VT == MVT::v8i8)
8717 if (ST->hasMVEIntegerOps())
8726 EVT VecVT =
Op.getOperand(0).getValueType();
8729 assert(ST->hasMVEIntegerOps() &&
8730 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8733 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8734 unsigned Lane =
Op.getConstantOperandVal(2);
8735 unsigned LaneWidth =
8737 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8742 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8755 if (Subtarget->hasMVEIntegerOps() &&
8756 Op.getValueType().getScalarSizeInBits() == 1)
8780 IVecIn, IElt, Lane);
8781 return DAG.
getNode(ISD::BITCAST, dl, VecVT, IVecOut);
8789 EVT VecVT =
Op.getOperand(0).getValueType();
8792 assert(ST->hasMVEIntegerOps() &&
8793 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8796 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8797 unsigned Lane =
Op.getConstantOperandVal(1);
8798 unsigned LaneWidth =
8820 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8829 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8830 "Unexpected custom CONCAT_VECTORS lowering");
8832 "Unexpected custom CONCAT_VECTORS lowering");
8833 assert(ST->hasMVEIntegerOps() &&
8834 "CONCAT_VECTORS lowering only supported for MVE");
8838 EVT Op2VT = V2.getValueType();
8839 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8840 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8841 "Unexpected i1 concat operations!");
8854 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8859 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8868 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8869 EVT NewVT = NewV.getValueType();
8870 EVT ConcatVT = ConVec.getValueType();
8871 unsigned ExtScale = 1;
8872 if (NewVT == MVT::v2f64) {
8873 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8886 ConVec = ExtractInto(NewV1, ConVec, j);
8887 ConVec = ExtractInto(NewV2, ConVec, j);
8891 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8897 while (ConcatOps.
size() > 1) {
8898 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8901 ConcatOps[
I / 2] = ConcatPair(V1, V2);
8905 return ConcatOps[0];
8910 EVT VT =
Op->getValueType(0);
8916 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
8917 "unexpected CONCAT_VECTORS");
8924 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op0),
8928 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op1),
8930 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Val);
8938 EVT VT =
Op.getValueType();
8944 "Unexpected custom EXTRACT_SUBVECTOR lowering");
8945 assert(ST->hasMVEIntegerOps() &&
8946 "EXTRACT_SUBVECTOR lowering only supported for MVE");
8956 EVT SubVT = MVT::v4i32;
8958 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
8968 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8973 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
8982 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
8989 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
8990 EVT VT =
N->getValueType(0);
8991 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
8992 "Expected a vector i1 type!");
8994 EVT FromVT =
Op.getValueType();
9005 if (!Subtarget->hasMVEIntegerOps())
9008 EVT ToVT =
N->getValueType(0);
9051 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9053 EVT FromVT =
N->getOperand(0).getValueType();
9054 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9065 if (!Subtarget->hasMVEIntegerOps())
9070 EVT ToVT =
N->getValueType(0);
9071 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9074 EVT FromVT =
Op.getValueType();
9075 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9086 SDValue Ext1 = Ext.getValue(1);
9089 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9090 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9102 EVT VT =
N->getValueType(0);
9103 if (VT == MVT::v2i64 &&
N->getOpcode() == ISD::BITCAST) {
9104 SDNode *BVN =
N->getOperand(0).getNode();
9109 unsigned HiElt = 1 - LoElt;
9114 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9130 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9131 SDNode *Elt =
N->getOperand(i).getNode();
9134 unsigned HalfSize = EltSize / 2;
9136 if (!
isIntN(HalfSize,
C->getSExtValue()))
9139 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9178 switch (OrigSimpleTy) {
9194 unsigned ExtOpcode) {
9217 if (ExtendedTy == LD->getMemoryVT())
9218 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9219 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9220 LD->getMemOperand()->getFlags());
9226 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9227 LD->getMemoryVT(), LD->getAlign(),
9228 LD->getMemOperand()->getFlags());
9241 N->getOperand(0)->getValueType(0),
9247 "Expected extending load");
9253 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9261 if (
N->getOpcode() == ISD::BITCAST) {
9262 SDNode *BVN =
N->getOperand(0).getNode();
9264 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9272 EVT VT =
N->getValueType(0);
9278 for (
unsigned i = 0; i != NumElts; ++i) {
9279 const APInt &CInt =
N->getConstantOperandAPInt(i);
9288 unsigned Opcode =
N->getOpcode();
9290 SDNode *N0 =
N->getOperand(0).getNode();
9291 SDNode *N1 =
N->getOperand(1).getNode();
9299 unsigned Opcode =
N->getOpcode();
9301 SDNode *N0 =
N->getOperand(0).getNode();
9302 SDNode *N1 =
N->getOperand(1).getNode();
9312 EVT VT =
Op.getValueType();
9314 "unexpected type for custom-lowering ISD::MUL");
9315 SDNode *N0 =
Op.getOperand(0).getNode();
9316 SDNode *N1 =
Op.getOperand(1).getNode();
9317 unsigned NewOpc = 0;
9321 if (isN0SExt && isN1SExt)
9322 NewOpc = ARMISD::VMULLs;
9326 if (isN0ZExt && isN1ZExt)
9327 NewOpc = ARMISD::VMULLu;
9328 else if (isN1SExt || isN1ZExt) {
9332 NewOpc = ARMISD::VMULLs;
9335 NewOpc = ARMISD::VMULLu;
9339 NewOpc = ARMISD::VMULLu;
9345 if (VT == MVT::v2i64)
9362 "unexpected types for extended operands to VMULL");
9363 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9379 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N00), Op1),
9381 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N01), Op1));
9398 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9405 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32,
X);
9408 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32,
X);
9432 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9435 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9443 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9446 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9456 EVT VT =
Op.getValueType();
9457 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9458 "unexpected type for custom-lowering ISD::SDIV");
9465 if (VT == MVT::v8i8) {
9493 EVT VT =
Op.getValueType();
9494 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9495 "unexpected type for custom-lowering ISD::UDIV");
9502 if (VT == MVT::v8i8) {
9541 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9544 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9548 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9556 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9559 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9569 EVT VT =
N->getValueType(0);
9582 Result = DAG.
getNode(ARMISD::ADDE,
DL, VTs,
Op.getOperand(0),
9583 Op.getOperand(1), Carry);
9596 Result = DAG.
getNode(ARMISD::SUBE,
DL, VTs,
Op.getOperand(0),
9597 Op.getOperand(1), Carry);
9614 EVT VT =
Op.getValueType();
9615 assert((VT == MVT::i32 || VT == MVT::i64) &&
9616 "unexpected type for custom lowering DIV");
9622 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9624 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9631 for (
auto AI : {1, 0}) {
9633 Args.emplace_back(Operand,
9641 ES, std::move(Args));
9651ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9659 const bool MinSize =
ST.hasMinSize();
9660 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9661 :
ST.hasDivideInARMMode();
9665 if (
N->getOperand(0).getValueType().isVector())
9670 if (!(MinSize && HasDivide))
9683 if (Divisor.
sgt(128))
9691 assert(
Op.getValueType() == MVT::i32 &&
9692 "unexpected type for custom lowering DIV");
9695 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9698 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9704 if (
N->getValueType(0) == MVT::i32)
9705 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9708 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9712void ARMTargetLowering::ExpandDIV_Windows(
9717 assert(
Op.getValueType() == MVT::i64 &&
9718 "unexpected type for custom lowering DIV");
9735 EVT MemVT = LD->getMemoryVT();
9736 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9737 MemVT == MVT::v16i1) &&
9738 "Expected a predicate type!");
9739 assert(MemVT ==
Op.getValueType());
9741 "Expected a non-extending load");
9742 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9756 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9758 LD->getMemOperand());
9764 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9765 if (MemVT != MVT::v16i1)
9774 EVT MemVT =
LD->getMemoryVT();
9775 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9777 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9778 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9779 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9782 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9783 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9793 EVT MemVT = ST->getMemoryVT();
9794 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9795 MemVT == MVT::v16i1) &&
9796 "Expected a predicate type!");
9797 assert(MemVT == ST->getValue().getValueType());
9798 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9799 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9804 SDValue Build = ST->getValue();
9805 if (MemVT != MVT::v16i1) {
9818 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9824 ST->getChain(), dl, GRP, ST->getBasePtr(),
9826 ST->getMemOperand());
9832 EVT MemVT = ST->getMemoryVT();
9833 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
9835 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9851 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
9852 MemVT, ST->getMemOperand());
9853 }
else if (Subtarget->hasMVEIntegerOps() &&
9854 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9855 MemVT == MVT::v16i1))) {
9864 (
N->getOpcode() == ARMISD::VMOVIMM &&
9870 MVT VT =
Op.getSimpleValueType();
9872 SDValue PassThru =
N->getPassThru();
9883 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
9884 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
9885 N->getExtensionType(),
N->isExpandingLoad());
9887 bool PassThruIsCastZero = (PassThru.
getOpcode() == ISD::BITCAST ||
9888 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
9890 if (!PassThru.
isUndef() && !PassThruIsCastZero)
9897 if (!ST->hasMVEIntegerOps())
9901 unsigned BaseOpcode = 0;
9902 switch (
Op->getOpcode()) {
9904 case ISD::VECREDUCE_FADD: BaseOpcode =
ISD::FADD;
break;
9905 case ISD::VECREDUCE_FMUL: BaseOpcode =
ISD::FMUL;
break;
9906 case ISD::VECREDUCE_MUL: BaseOpcode =
ISD::MUL;
break;
9907 case ISD::VECREDUCE_AND: BaseOpcode =
ISD::AND;
break;
9908 case ISD::VECREDUCE_OR: BaseOpcode =
ISD::OR;
break;
9909 case ISD::VECREDUCE_XOR: BaseOpcode =
ISD::XOR;
break;
9910 case ISD::VECREDUCE_FMAX: BaseOpcode = ISD::FMAXNUM;
break;
9911 case ISD::VECREDUCE_FMIN: BaseOpcode = ISD::FMINNUM;
break;
9918 unsigned NumActiveLanes = NumElts;
9920 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
9921 NumActiveLanes == 2) &&
9922 "Only expected a power 2 vector size");
9926 while (NumActiveLanes > 4) {
9927 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
9929 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
9930 NumActiveLanes /= 2;
9934 if (NumActiveLanes == 4) {
9944 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
9945 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
9946 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
9952 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
9956 if (EltVT !=
Op->getValueType(0))
9963 if (!ST->hasMVEFloatOps())
9978 unsigned PairwiseIntrinsic = 0;
9979 switch (
Op->getOpcode()) {
9982 case ISD::VECREDUCE_UMIN:
9983 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
9985 case ISD::VECREDUCE_UMAX:
9986 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
9988 case ISD::VECREDUCE_SMIN:
9989 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
9991 case ISD::VECREDUCE_SMAX:
9992 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
9998 unsigned NumActiveLanes = NumElts;
10000 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10001 NumActiveLanes == 2) &&
10002 "Only expected a power 2 vector size");
10008 VT =
Lo.getValueType();
10010 NumActiveLanes /= 2;
10014 while (NumActiveLanes > 1) {
10016 NumActiveLanes /= 2;
10023 if (EltVT !=
Op.getValueType()) {
10024 unsigned Extend = 0;
10025 switch (
Op->getOpcode()) {
10028 case ISD::VECREDUCE_UMIN:
10029 case ISD::VECREDUCE_UMAX:
10032 case ISD::VECREDUCE_SMIN:
10033 case ISD::VECREDUCE_SMAX:
10037 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10082 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10088 SDLoc dl(V.getNode());
10089 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10099 assert(
N->getValueType(0) == MVT::i64 &&
10100 "AtomicCmpSwap on types less than 64 should be legal");
10109 ARM::CMP_SWAP_64,
SDLoc(
N),
10110 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10129 EVT VT =
Op.getValueType();
10138 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10140 Chain, IsSignaling);
10141 if (!
RHS.getNode()) {
10157 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10159 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10160 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10177 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10180 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10193 if (!IsSigned && Subtarget->isThumb1Only()) {
10211 Sub1Result, Sub1Result, Flags1);
10226 if (
Op.getValueType() != MVT::i32)
10240 unsigned Opcode = ARMISD::SUBC;
10249 bool CanUseAdd =
false;
10265 Opcode = ARMISD::ADDC;
10289 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10290 GTCondValue, Flags);
10294 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10295 LTCondValue, Flags);
10297 if (
Op.getValueType() != MVT::i32)
10305 switch (
Op.getOpcode()) {
10314 case ISD::BRCOND:
return LowerBRCOND(
Op, DAG);
10315 case ISD::BR_CC:
return LowerBR_CC(
Op, DAG);
10316 case ISD::BR_JT:
return LowerBR_JT(
Op, DAG);
10337 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10341 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10342 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10362 case ISD::SET_ROUNDING:
return LowerSET_ROUNDING(
Op, DAG);
10363 case ISD::SET_FPMODE:
10364 return LowerSET_FPMODE(
Op, DAG);
10365 case ISD::RESET_FPMODE:
10366 return LowerRESET_FPMODE(
Op, DAG);
10369 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10370 return LowerDIV_Windows(
Op, DAG,
true);
10373 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10374 return LowerDIV_Windows(
Op, DAG,
false);
10381 return LowerSignedALUO(
Op, DAG);
10384 return LowerUnsignedALUO(
Op, DAG);
10396 case ISD::VECREDUCE_MUL:
10397 case ISD::VECREDUCE_AND:
10398 case ISD::VECREDUCE_OR:
10399 case ISD::VECREDUCE_XOR:
10401 case ISD::VECREDUCE_FADD:
10402 case ISD::VECREDUCE_FMUL:
10403 case ISD::VECREDUCE_FMIN:
10404 case ISD::VECREDUCE_FMAX:
10406 case ISD::VECREDUCE_UMIN:
10407 case ISD::VECREDUCE_UMAX:
10408 case ISD::VECREDUCE_SMIN:
10409 case ISD::VECREDUCE_SMAX:
10411 case ISD::ATOMIC_LOAD:
10412 case ISD::ATOMIC_STORE:
10416 case ISD::DYNAMIC_STACKALLOC:
10417 if (Subtarget->isTargetWindows())
10418 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10423 case ISD::FP_EXTEND:
return LowerFP_EXTEND(
Op, DAG);
10427 return LowerSPONENTRY(
Op, DAG);
10428 case ISD::FP_TO_BF16:
10429 return LowerFP_TO_BF16(
Op, DAG);
10430 case ARMISD::WIN__DBZCHK:
return SDValue();
10433 return LowerCMP(
Op, DAG);
10435 return LowerABS(
Op, DAG);
10440 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10441 Op.getOperand(1).getValueType() == MVT::bf16) &&
10442 "Expected custom lowering of rounding operations only for f16");
10445 {
Op.getOperand(0),
Op.getOperand(1)});
10446 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10447 {Ext.getValue(1), Ext.getValue(0)});
10454 unsigned IntNo =
N->getConstantOperandVal(0);
10456 if (IntNo == Intrinsic::arm_smlald)
10457 Opc = ARMISD::SMLALD;
10458 else if (IntNo == Intrinsic::arm_smlaldx)
10459 Opc = ARMISD::SMLALDX;
10460 else if (IntNo == Intrinsic::arm_smlsld)
10461 Opc = ARMISD::SMLSLD;
10462 else if (IntNo == Intrinsic::arm_smlsldx)
10463 Opc = ARMISD::SMLSLDX;
10469 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10473 N->getOperand(1),
N->getOperand(2),
10485 switch (
N->getOpcode()) {
10492 Res = ExpandBITCAST(
N, DAG, Subtarget);
10501 Res = LowerREM(
N, DAG);
10505 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10516 case ISD::READCYCLECOUNTER:
10521 assert(Subtarget->isTargetWindows() &&
"can only expand DIV on Windows");
10524 case ISD::ATOMIC_CMP_SWAP:
10559 "ROPI/RWPI not currently supported with SjLj");
10568 bool isThumb = Subtarget->isThumb();
10569 bool isThumb2 = Subtarget->
isThumb2();
10572 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10578 : &ARM::GPRRegClass;
10596 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10602 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10608 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10626 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10631 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10636 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10641 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10647 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10662 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10668 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10684 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10691 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10692 : &ARM::GPRnopcRegClass;
10696 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10697 unsigned MaxCSNum = 0;
10698 for (MachineBasicBlock &BB : *MF) {
10704 for (MachineInstr &
II : BB) {
10705 if (!
II.isEHLabel())
10708 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10709 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10711 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10712 for (
unsigned Idx : CallSiteIdxs) {
10713 CallSiteNumToLPad[Idx].push_back(&BB);
10714 MaxCSNum = std::max(MaxCSNum, Idx);
10721 std::vector<MachineBasicBlock*> LPadList;
10722 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10723 LPadList.reserve(CallSiteNumToLPad.
size());
10724 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10725 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10726 for (MachineBasicBlock *
MBB : MBBList) {
10727 LPadList.push_back(
MBB);
10732 assert(!LPadList.empty() &&
10733 "No landing pad destinations for the dispatch jump table!");
10736 MachineJumpTableInfo *JTI =
10743 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10746 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10748 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10751 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10755 MF->insert(MF->end(), DispatchBB);
10756 MF->insert(MF->end(), DispContBB);
10757 MF->insert(MF->end(), TrapBB);
10761 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10763 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10767 MachineInstrBuilder MIB;
10768 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10770 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10780 unsigned NumLPads = LPadList.size();
10781 if (Subtarget->isThumb2()) {
10782 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10783 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10789 if (NumLPads < 256) {
10790 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10792 .
addImm(LPadList.size())
10795 Register VReg1 =
MRI->createVirtualRegister(TRC);
10796 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10797 .
addImm(NumLPads & 0xFFFF)
10800 unsigned VReg2 = VReg1;
10801 if ((NumLPads & 0xFFFF0000) != 0) {
10802 VReg2 =
MRI->createVirtualRegister(TRC);
10803 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10809 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
10815 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
10820 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10821 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
10825 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10826 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
10833 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
10837 }
else if (Subtarget->isThumb()) {
10838 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10839 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
10845 if (NumLPads < 256) {
10846 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
10851 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10856 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
10857 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
10859 Register VReg1 =
MRI->createVirtualRegister(TRC);
10860 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
10864 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
10870 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
10875 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10876 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
10882 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10883 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
10887 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10888 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
10894 MachineMemOperand *JTMMOLd =
10898 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10899 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
10905 unsigned NewVReg6 = NewVReg5;
10906 if (IsPositionIndependent) {
10907 NewVReg6 =
MRI->createVirtualRegister(TRC);
10908 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
10915 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
10919 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10920 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
10926 if (NumLPads < 256) {
10927 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
10931 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
10932 Register VReg1 =
MRI->createVirtualRegister(TRC);
10933 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
10934 .
addImm(NumLPads & 0xFFFF)
10937 unsigned VReg2 = VReg1;
10938 if ((NumLPads & 0xFFFF0000) != 0) {
10939 VReg2 =
MRI->createVirtualRegister(TRC);
10940 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
10946 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
10951 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10956 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
10957 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
10959 Register VReg1 =
MRI->createVirtualRegister(TRC);
10960 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
10965 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
10976 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10977 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
10982 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10983 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
10987 MachineMemOperand *JTMMOLd =
10990 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10991 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
10998 if (IsPositionIndependent) {
10999 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11004 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11011 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11012 for (MachineBasicBlock *CurMBB : LPadList) {
11013 if (SeenMBBs.
insert(CurMBB).second)
11020 for (MachineBasicBlock *BB : InvokeBBs) {
11024 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11025 while (!Successors.empty()) {
11026 MachineBasicBlock *SMBB = Successors.pop_back_val();
11028 BB->removeSuccessor(SMBB);
11034 BB->normalizeSuccProbs();
11041 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11042 if (!
II->isCall())
continue;
11044 DenseSet<unsigned> DefRegs;
11046 OI =
II->operands_begin(), OE =
II->operands_end();
11048 if (!OI->isReg())
continue;
11049 DefRegs.
insert(OI->getReg());
11052 MachineInstrBuilder MIB(*MF, &*
II);
11054 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11055 unsigned Reg = SavedRegs[i];
11056 if (Subtarget->isThumb2() &&
11057 !ARM::tGPRRegClass.contains(
Reg) &&
11058 !ARM::hGPRRegClass.contains(
Reg))
11060 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11062 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11074 for (MachineBasicBlock *MBBLPad : MBBLPads)
11075 MBBLPad->setIsEHPad(
false);
11078 MI.eraseFromParent();
11091static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11093 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11094 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11096 return LdSize == 4 ? ARM::tLDRi
11097 : LdSize == 2 ? ARM::tLDRHi
11098 : LdSize == 1 ? ARM::tLDRBi : 0;
11100 return LdSize == 4 ? ARM::t2LDR_POST
11101 : LdSize == 2 ? ARM::t2LDRH_POST
11102 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11103 return LdSize == 4 ? ARM::LDR_POST_IMM
11104 : LdSize == 2 ? ARM::LDRH_POST
11105 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11110static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11112 return StSize == 16 ? ARM::VST1q32wb_fixed
11113 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11115 return StSize == 4 ? ARM::tSTRi
11116 : StSize == 2 ? ARM::tSTRHi
11117 : StSize == 1 ? ARM::tSTRBi : 0;
11119 return StSize == 4 ? ARM::t2STR_POST
11120 : StSize == 2 ? ARM::t2STRH_POST
11121 : StSize == 1 ? ARM::t2STRB_POST : 0;
11122 return StSize == 4 ? ARM::STR_POST_IMM
11123 : StSize == 2 ? ARM::STRH_POST
11124 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11131 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11132 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11133 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11134 assert(LdOpc != 0 &&
"Should have a load opcode");
11141 }
else if (IsThumb1) {
11147 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11152 }
else if (IsThumb2) {
11172 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11173 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11174 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11175 assert(StOpc != 0 &&
"Should have a store opcode");
11177 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11182 }
else if (IsThumb1) {
11189 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11194 }
else if (IsThumb2) {
11195 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11201 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11216 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11222 unsigned SizeVal =
MI.getOperand(2).getImm();
11223 unsigned Alignment =
MI.getOperand(3).getImm();
11228 unsigned UnitSize = 0;
11229 const TargetRegisterClass *TRC =
nullptr;
11230 const TargetRegisterClass *VecTRC =
nullptr;
11232 bool IsThumb1 = Subtarget->isThumb1Only();
11233 bool IsThumb2 = Subtarget->isThumb2();
11234 bool IsThumb = Subtarget->isThumb();
11236 if (Alignment & 1) {
11238 }
else if (Alignment & 2) {
11243 Subtarget->hasNEON()) {
11244 if ((Alignment % 16 == 0) && SizeVal >= 16)
11246 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11255 bool IsNeon = UnitSize >= 8;
11256 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11258 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11259 : UnitSize == 8 ? &ARM::DPRRegClass
11262 unsigned BytesLeft = SizeVal % UnitSize;
11263 unsigned LoopSize = SizeVal - BytesLeft;
11265 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11269 unsigned srcIn = src;
11270 unsigned destIn = dest;
11271 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11272 Register srcOut =
MRI.createVirtualRegister(TRC);
11273 Register destOut =
MRI.createVirtualRegister(TRC);
11274 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11276 IsThumb1, IsThumb2);
11278 IsThumb1, IsThumb2);
11286 for (
unsigned i = 0; i < BytesLeft; i++) {
11287 Register srcOut =
MRI.createVirtualRegister(TRC);
11288 Register destOut =
MRI.createVirtualRegister(TRC);
11289 Register scratch =
MRI.createVirtualRegister(TRC);
11291 IsThumb1, IsThumb2);
11293 IsThumb1, IsThumb2);
11297 MI.eraseFromParent();
11323 MF->
insert(It, loopMBB);
11324 MF->
insert(It, exitMBB);
11327 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11337 Register varEnd =
MRI.createVirtualRegister(TRC);
11338 if (Subtarget->useMovt()) {
11339 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11342 }
else if (Subtarget->genExecuteOnly()) {
11343 assert(IsThumb &&
"Non-thumb expected to have used movt");
11352 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11353 MachineMemOperand *CPMMO =
11377 MachineBasicBlock *entryBB = BB;
11379 Register varLoop =
MRI.createVirtualRegister(TRC);
11380 Register varPhi =
MRI.createVirtualRegister(TRC);
11381 Register srcLoop =
MRI.createVirtualRegister(TRC);
11382 Register srcPhi =
MRI.createVirtualRegister(TRC);
11383 Register destLoop =
MRI.createVirtualRegister(TRC);
11384 Register destPhi =
MRI.createVirtualRegister(TRC);
11392 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11398 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11400 IsThumb1, IsThumb2);
11402 IsThumb1, IsThumb2);
11406 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11412 MachineInstrBuilder MIB =
11414 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11423 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11432 auto StartOfExit = exitMBB->
begin();
11436 unsigned srcIn = srcLoop;
11437 unsigned destIn = destLoop;
11438 for (
unsigned i = 0; i < BytesLeft; i++) {
11439 Register srcOut =
MRI.createVirtualRegister(TRC);
11440 Register destOut =
MRI.createVirtualRegister(TRC);
11441 Register scratch =
MRI.createVirtualRegister(TRC);
11442 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11443 IsThumb1, IsThumb2);
11444 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11445 IsThumb1, IsThumb2);
11450 MI.eraseFromParent();
11458 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11461 assert(Subtarget->isTargetWindows() &&
11462 "__chkstk is only supported on Windows");
11463 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11483 switch (TM.getCodeModel()) {
11525 MI.eraseFromParent();
11534 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11549 .
addReg(
MI.getOperand(0).getReg())
11557 MI.eraseFromParent();
11581 if (miI == BB->
end()) {
11583 if (Succ->isLiveIn(ARM::CPSR))
11589 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11601 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11602 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11608 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11609 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11615 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11616 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11619 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11620 .
addUse(TotalIterationsReg)
11627 return TotalIterationsReg;
11638 Register TotalIterationsReg,
bool IsMemcpy) {
11645 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11646 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11647 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11655 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11656 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11657 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11664 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11665 Register RemainingLoopIterationsReg =
11666 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11667 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11668 .
addUse(TotalIterationsReg)
11670 .
addUse(RemainingLoopIterationsReg)
11674 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11675 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11676 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11677 .
addUse(ElementCountReg)
11679 .
addUse(RemainingElementsReg)
11683 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11684 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11685 .
addUse(PredCounterPhiReg)
11690 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11691 .
addUse(PredCounterPhiReg)
11699 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11700 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11709 SrcValueReg = OpSrcReg;
11711 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11722 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11723 .
addUse(LoopCounterPhiReg)
11726 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11727 .
addUse(RemainingLoopIterationsReg)
11745 "Invalid call instruction for a KCFI check");
11748 switch (
MBBI->getOpcode()) {
11751 case ARM::BLX_pred:
11752 case ARM::BLX_noip:
11753 case ARM::BLX_pred_noip:
11755 TargetOp = &
MBBI->getOperand(0);
11757 case ARM::TCRETURNri:
11758 case ARM::TCRETURNrinotr12:
11759 case ARM::TAILJMPr:
11760 case ARM::TAILJMPr4:
11761 TargetOp = &
MBBI->getOperand(0);
11767 case ARM::tBLXr_noip:
11768 case ARM::tBX_CALL:
11769 TargetOp = &
MBBI->getOperand(2);
11772 case ARM::tTAILJMPr:
11773 TargetOp = &
MBBI->getOperand(0);
11779 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11783 unsigned KCFICheckOpcode;
11784 if (Subtarget->isThumb()) {
11785 if (Subtarget->isThumb2()) {
11786 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11788 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11791 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11805 bool isThumb2 = Subtarget->isThumb2();
11806 switch (
MI.getOpcode()) {
11813 case ARM::tLDR_postidx: {
11817 .
add(
MI.getOperand(2))
11818 .
add(
MI.getOperand(3))
11819 .
add(
MI.getOperand(4))
11820 .
add(
MI.getOperand(0))
11822 MI.eraseFromParent();
11826 case ARM::MVE_MEMCPYLOOPINST:
11827 case ARM::MVE_MEMSETLOOPINST: {
11857 Register OpDestReg =
MI.getOperand(0).getReg();
11858 Register OpSrcReg =
MI.getOperand(1).getReg();
11859 Register OpSizeReg =
MI.getOperand(2).getReg();
11879 if (TpExit == BB) {
11881 "block containing memcpy/memset Pseudo");
11894 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
11896 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
11899 Properties.resetNoPHIs();
11911 MI.eraseFromParent();
11921 case ARM::t2STR_preidx:
11922 MI.setDesc(
TII->get(ARM::t2STR_PRE));
11924 case ARM::t2STRB_preidx:
11925 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
11927 case ARM::t2STRH_preidx:
11928 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
11931 case ARM::STRi_preidx:
11932 case ARM::STRBi_preidx: {
11933 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
11934 : ARM::STRB_PRE_IMM;
11936 unsigned Offset =
MI.getOperand(4).getImm();
11944 .
add(
MI.getOperand(0))
11945 .
add(
MI.getOperand(1))
11946 .
add(
MI.getOperand(2))
11948 .
add(
MI.getOperand(5))
11949 .
add(
MI.getOperand(6))
11951 MI.eraseFromParent();
11954 case ARM::STRr_preidx:
11955 case ARM::STRBr_preidx:
11956 case ARM::STRH_preidx: {
11958 switch (
MI.getOpcode()) {
11960 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
11961 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
11962 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
11967 MI.eraseFromParent();
11971 case ARM::tMOVCCr_pseudo: {
11989 F->insert(It, copy0MBB);
11990 F->insert(It, sinkMBB);
11993 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11999 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12015 .
addImm(
MI.getOperand(3).getImm())
12016 .
addReg(
MI.getOperand(4).getReg());
12031 .
addReg(
MI.getOperand(1).getReg())
12033 .
addReg(
MI.getOperand(2).getReg())
12036 MI.eraseFromParent();
12041 case ARM::BCCZi64: {
12047 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12052 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12056 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12062 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12066 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12076 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12085 MI.eraseFromParent();
12089 case ARM::Int_eh_sjlj_setjmp:
12090 case ARM::Int_eh_sjlj_setjmp_nofp:
12091 case ARM::tInt_eh_sjlj_setjmp:
12092 case ARM::t2Int_eh_sjlj_setjmp:
12093 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12096 case ARM::Int_eh_sjlj_setup_dispatch:
12097 EmitSjLjDispatchBlock(
MI, BB);
12099 case ARM::COPY_STRUCT_BYVAL_I32:
12101 return EmitStructByval(
MI, BB);
12102 case ARM::WIN__CHKSTK:
12103 return EmitLowered__chkstk(
MI, BB);
12104 case ARM::WIN__DBZCHK:
12105 return EmitLowered__dbzchk(
MI, BB);
12121 if (!
Node->hasAnyUseOfValue(0)) {
12122 MI.getOperand(0).setIsDead(
true);
12124 if (!
Node->hasAnyUseOfValue(1)) {
12125 MI.getOperand(1).setIsDead(
true);
12129 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12130 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12131 : &ARM::GPRRegClass);
12138 if (
MI.getOpcode() == ARM::MEMCPY) {
12159 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12160 &&
"converted opcode should be the same except for cc_out"
12161 " (and, on Thumb1, pred)");
12169 if (Subtarget->isThumb1Only()) {
12170 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12171 MI.addOperand(
MI.getOperand(1));
12172 MI.removeOperand(1);
12176 for (
unsigned i =
MI.getNumOperands(); i--;) {
12178 if (
op.isReg() &&
op.isUse()) {
12181 MI.tieOperands(DefIdx, i);
12189 ccOutIdx =
MCID->getNumOperands() - 1;
12191 ccOutIdx =
MCID->getNumOperands() - 1;
12195 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12196 assert(!NewOpc &&
"Optional cc_out operand required");
12201 bool definesCPSR =
false;
12202 bool deadCPSR =
false;
12203 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12207 definesCPSR =
true;
12210 MI.removeOperand(i);
12214 if (!definesCPSR) {
12215 assert(!NewOpc &&
"Optional cc_out operand required");
12218 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12220 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12221 "expect uninitialized optional cc_out operand");
12223 if (!Subtarget->isThumb1Only())
12259 switch (
N->getOpcode()) {
12260 default:
return false;
12262 CC =
N->getOperand(0);
12284 EVT VT =
N->getValueType(0);
12285 CC =
N->getOperand(0);
12332 EVT VT =
N->getValueType(0);
12335 bool SwapSelectOps;
12337 NonConstantVal, DAG))
12343 OtherOp, NonConstantVal);
12349 CCOp, TrueVal, FalseVal);
12369 if (
N->getOpcode() == ARMISD::VUZP)
12373 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12388 if (!
N->getValueType(0).is64BitVector())
12396 EVT VT =
N->getValueType(0);
12435 EVT VT =
N->getValueType(0);
12441 Opcode = Intrinsic::arm_neon_vpaddls;
12443 Opcode = Intrinsic::arm_neon_vpaddlu;
12471 EVT VT =
N->getValueType(0);
12486 unsigned nextIndex = 0;
12537 Ops.push_back(Vec);
12554 return DAG.
getNode(ExtOp, dl, VT, tmp);
12585 if (SRA.getOpcode() !=
ISD::SRA) {
12592 if (Const->getZExtValue() != 31)
12597 if (SRA.getOperand(0) !=
Mul)
12601 SDLoc dl(AddcNode);
12602 unsigned Opcode = 0;
12607 Opcode = ARMISD::SMLALBB;
12608 Op0 =
Mul.getOperand(0);
12609 Op1 =
Mul.getOperand(1);
12611 Opcode = ARMISD::SMLALBT;
12612 Op0 =
Mul.getOperand(0);
12613 Op1 =
Mul.getOperand(1).getOperand(0);
12615 Opcode = ARMISD::SMLALTB;
12616 Op0 =
Mul.getOperand(0).getOperand(0);
12617 Op1 =
Mul.getOperand(1);
12619 Opcode = ARMISD::SMLALTT;
12620 Op0 =
Mul->getOperand(0).getOperand(0);
12621 Op1 =
Mul->getOperand(1).getOperand(0);
12637 SDValue resNode(AddcNode, 0);
12665 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12666 "Expect an ADDE or SUBE");
12670 "ADDE node has the wrong inputs");
12674 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12675 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12676 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12677 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12689 "Expect ADDC with two result values. First: i32");
12693 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12709 bool IsLeftOperandMUL =
false;
12714 IsLeftOperandMUL =
true;
12725 SDValue *LowAddSub =
nullptr;
12728 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12731 if (IsLeftOperandMUL)
12732 HiAddSub = &AddeSubeOp1;
12734 HiAddSub = &AddeSubeOp0;
12739 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12740 LoMul = &AddcSubcOp0;
12741 LowAddSub = &AddcSubcOp1;
12743 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12744 LoMul = &AddcSubcOp1;
12745 LowAddSub = &AddcSubcOp0;
12753 if (AddcSubcNode == HiAddSub->getNode() ||
12769 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12774 Ops.push_back(*HiAddSub);
12775 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12776 FinalOpc = ARMISD::SMMLSR;
12778 FinalOpc = ARMISD::SMMLAR;
12783 return SDValue(AddeSubeNode, 0);
12784 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12790 Ops.push_back(*LowAddSub);
12791 Ops.push_back(*HiAddSub);
12804 return SDValue(AddeSubeNode, 0);
12816 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12821 if (AddcNode->
getOpcode() != ARMISD::ADDC)
12825 SDNode *UmlalNode =
nullptr;
12864 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12869 SDNode* AddcNode =
N->getOperand(2).getNode();
12870 SDNode* AddeNode =
N->getOperand(3).getNode();
12871 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
12872 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
12878 {N->getOperand(0), N->getOperand(1),
12879 AddcNode->getOperand(0), AddcNode->getOperand(1)});
12889 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
12893 if (
LHS->getOpcode() == ARMISD::ADDE &&
12903 int32_t imm =
C->getSExtValue();
12904 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
12907 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
12909 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
12924 int64_t imm =
C->getSExtValue();
12933 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
12935 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
12936 N->getOperand(0),
RHS,
N->getOperand(2));
12948 if (!Subtarget->hasMVEIntegerOps())
12961 SetCC =
N->getOperand(0);
12965 TrueVal =
N->getOperand(1);
12966 FalseVal =
N->getOperand(2);
12968 LHS =
N->getOperand(0);
12969 RHS =
N->getOperand(1);
12971 TrueVal =
N->getOperand(2);
12972 FalseVal =
N->getOperand(3);
12977 unsigned int Opcode = 0;
12978 if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMIN ||
12979 FalseVal->getOpcode() == ISD::VECREDUCE_UMIN) &&
12981 Opcode = ARMISD::VMINVu;
12984 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMIN ||
12985 FalseVal->getOpcode() == ISD::VECREDUCE_SMIN) &&
12987 Opcode = ARMISD::VMINVs;
12990 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMAX ||
12991 FalseVal->getOpcode() == ISD::VECREDUCE_UMAX) &&
12993 Opcode = ARMISD::VMAXVu;
12996 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMAX ||
12997 FalseVal->getOpcode() == ISD::VECREDUCE_SMAX) &&
12999 Opcode = ARMISD::VMAXVs;
13006 switch (TrueVal->getOpcode()) {
13007 case ISD::VECREDUCE_UMIN:
13008 case ISD::VECREDUCE_SMIN:
13009 case ISD::VECREDUCE_UMAX:
13010 case ISD::VECREDUCE_SMAX:
13025 if (TrueVal !=
LHS || FalseVal !=
RHS)
13028 EVT LeftType =
LHS->getValueType(0);
13029 EVT RightType =
RHS->getValueType(0);
13032 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13036 if (VectorScalarType != MVT::i32)
13044 if (VectorScalarType != MVT::i32)
13057 EVT VT =
N->getValueType(0);
13065 Shft =
N->getOperand(0);
13072 Cmp.getOperand(0) !=
N->getOperand(1) ||
13073 Cmp.getOperand(1) !=
N->getOperand(2))
13075 Shft =
N->getOperand(1);
13087 ScalarType = MVT::i8;
13090 case (1 << 15) - 1:
13091 ScalarType = MVT::i16;
13094 case (1ULL << 31) - 1:
13095 ScalarType = MVT::i32;
13126 unsigned LegalLanes = 128 / (ShftAmt + 1);
13138 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13139 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13140 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13141 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13150 for (
unsigned I = 0;
I < NumParts; ++
I) {
13157 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13167 if (!Subtarget->hasMVEIntegerOps())
13182 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13192 if (!Const || !Const->isOne())
13210 EVT VT =
N->getValueType(0);
13212 if (!Subtarget->hasMVEIntegerOps() ||
13241 Opc = Intrinsic::arm_mve_vctp64;
13244 Opc = Intrinsic::arm_mve_vctp32;
13247 Opc = Intrinsic::arm_mve_vctp16;
13250 Opc = Intrinsic::arm_mve_vctp8;
13304 EVT VT =
N->getValueType(0);
13310 switch (
Op.getOpcode()) {
13311 case ISD::VECREDUCE_ADD:
13312 case ARMISD::VADDVs:
13313 case ARMISD::VADDVu:
13314 case ARMISD::VMLAVs:
13315 case ARMISD::VMLAVu:
13335 unsigned N0RedOp = 0;
13342 unsigned N1RedOp = 0;
13356 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13358 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13365 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13389 if (!BaseLocDecomp0.getBase() ||
13390 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13391 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13393 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13395 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13405 if (IsBefore < 0) {
13408 }
else if (IsBefore > 0) {
13421 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13431 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13441 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13443 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13450 if (!Subtarget->hasMVEIntegerOps())
13456 EVT VT =
N->getValueType(0);
13461 if (VT != MVT::i64)
13472 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13492 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13501 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13503 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13505 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13507 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13509 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13511 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13513 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13515 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13517 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13519 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13521 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13523 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13525 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13527 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13529 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13531 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13541 "Expected shift op");
13543 SDValue ShiftLHS =
N->getOperand(0);
13557 if (Subtarget->isThumb1Only()) {
13568 if (Const->getAPIntValue().ult(256))
13571 Const->getAPIntValue().sgt(-256))
13587 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13588 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13589 "Expected XOR(SHIFT) pattern");
13594 if (XorC && ShiftC) {
13595 unsigned MaskIdx, MaskLen;
13596 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13597 unsigned ShiftAmt = ShiftC->getZExtValue();
13598 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13599 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13600 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13601 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13611 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13613 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13614 "Expected shift-shift mask");
13616 if (!Subtarget->isThumb1Only())
13619 EVT VT =
N->getValueType(0);
13627 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13629 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13634 if (!Subtarget->hasNEON()) {
13635 if (Subtarget->isThumb1Only())
13649 return Subtarget->hasVFP2Base();
13651 return Subtarget->hasVFP2Base();
13653 return Subtarget->hasFP64();
13656 return Subtarget->hasMVEFloatOps();
13685 if (ST->isThumb() && ST->isThumb1Only())
13689 for (
auto *U :
N->users()) {
13690 switch(U->getOpcode()) {
13708 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13709 U->getOperand(1).getOpcode() ==
ISD::SHL)
13719 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13726 if (!C1ShlC2 || !C2)
13729 APInt C2Int = C2->getAPIntValue();
13730 APInt C1Int = C1ShlC2->getAPIntValue();
13732 if (C2Int.
uge(C2Width))
13738 if ((C1Int & Mask) != C1Int)
13745 auto LargeImm = [](
const APInt &Imm) {
13746 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13747 return Imm.getBitWidth() - Zeros > 8;
13750 if (LargeImm(C1Int) || LargeImm(C2Int))
13762 SHL.dump();
N->dump());
13865 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
13886 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
13907 if (!Subtarget->hasVMLxForwarding())
13926 EVT VT =
N->getValueType(0);
13937 EVT VT =
N->getValueType(0);
13938 if (VT != MVT::v2i64)
13949 return Op->getOperand(0);
13962 if (
And->getOpcode() == ISD::BITCAST)
13963 And =
And->getOperand(0);
13967 if (Mask->getOpcode() == ISD::BITCAST)
13968 Mask = Mask->getOperand(0);
13971 Mask.getValueType() != MVT::v4i32)
13977 return And->getOperand(0);
13982 if (
SDValue Op0 = IsSignExt(N0)) {
13983 if (
SDValue Op1 = IsSignExt(N1)) {
13984 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
13985 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
13986 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
13989 if (
SDValue Op0 = IsZeroExt(N0)) {
13990 if (
SDValue Op1 = IsZeroExt(N1)) {
13991 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
13992 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
13993 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14005 EVT VT =
N->getValueType(0);
14006 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14017 if (VT != MVT::i32)
14024 int64_t MulAmt =
C->getSExtValue();
14027 ShiftAmt = ShiftAmt & (32 - 1);
14032 MulAmt >>= ShiftAmt;
14093 if (
N->getValueType(0) != MVT::i32)
14102 if (C1 == 255 || C1 == 65535)
14105 SDNode *N0 =
N->getOperand(0).getNode();
14119 if (!C2 || C2 >= 32)
14163 if (Trailing == C2 && C2 + C3 < 32) {
14176 if (Leading == C2 && C2 + C3 < 32) {
14204 EVT VT =
N->getValueType(0);
14208 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14211 APInt SplatBits, SplatUndef;
14212 unsigned SplatBitSize;
14214 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14215 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14216 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14217 SplatBitSize == 64) {
14224 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14226 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14251 if (!Subtarget->hasV6Ops() ||
14252 (Subtarget->isThumb() &&
14253 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14256 SDValue SRL = OR->getOperand(0);
14257 SDValue SHL = OR->getOperand(1);
14260 SRL = OR->getOperand(1);
14261 SHL = OR->getOperand(0);
14268 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14272 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14273 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14274 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14293 unsigned Opcode = 0;
14294 if (
isS16(OpS16, DAG))
14295 Opcode = ARMISD::SMULWB;
14297 Opcode = ARMISD::SMULWT;
14312 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14315 EVT VT =
N->getValueType(0);
14330 if (VT != MVT::i32)
14343 if (Mask == 0xffff)
14350 if ((Val & ~Mask) != Val)
14356 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14375 (Mask == ~Mask2)) {
14378 if (Subtarget->hasDSP() &&
14379 (Mask == 0xffff || Mask == 0xffff0000))
14385 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14392 (~Mask == Mask2)) {
14395 if (Subtarget->hasDSP() &&
14396 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14452 if (
N->getOpcode() == ARMISD::VCMP)
14454 else if (
N->getOpcode() == ARMISD::VCMPZ)
14462 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14469 EVT VT =
N->getValueType(0);
14474 auto IsFreelyInvertable = [&](
SDValue V) {
14475 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14481 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14497 EVT VT =
N->getValueType(0);
14503 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14504 VT == MVT::v8i1 || VT == MVT::v16i1))
14507 APInt SplatBits, SplatUndef;
14508 unsigned SplatBitSize;
14510 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14511 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14512 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14513 SplatBitSize == 64) {
14520 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14522 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14549 unsigned SplatBitSize;
14552 APInt SplatBits0, SplatBits1;
14556 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14557 HasAnyUndefs) && !HasAnyUndefs) {
14558 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14559 HasAnyUndefs) && !HasAnyUndefs) {
14564 SplatBits0 == ~SplatBits1) {
14572 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14594 EVT VT =
N->getValueType(0);
14609 if (Subtarget->hasMVEIntegerOps()) {
14637 assert(
N->getOpcode() == ARMISD::BFI);
14640 ToMask =
~N->getConstantOperandAPInt(2);
14660 unsigned LastActiveBitInA =
A.countr_zero();
14661 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14662 return LastActiveBitInA - 1 == FirstActiveBitInB;
14667 APInt ToMask, FromMask;
14672 if (V.getOpcode() != ARMISD::BFI)
14675 APInt NewToMask, NewFromMask;
14677 if (NewFrom != From)
14681 if ((NewToMask & ToMask).getBoolValue())
14706 unsigned InvMask =
N->getConstantOperandVal(2);
14710 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14711 "undefined behavior");
14712 unsigned Mask = (1u << Width) - 1;
14714 if ((Mask & (~Mask2)) == 0)
14716 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14723 APInt ToMask1, FromMask1;
14726 APInt ToMask2, FromMask2;
14732 APInt NewFromMask = FromMask1 | FromMask2;
14733 APInt NewToMask = ToMask1 | ToMask2;
14735 EVT VT =
N->getValueType(0);
14738 if (NewFromMask[0] == 0)
14741 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
14749 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
14750 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14751 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14753 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14757 EVT VT =
N->getValueType(0);
14760 N->getOperand(1),
N->getOperand(2));
14772 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
14774 SDValue CSInc = Cmp->getOperand(0);
14784 if (CSInc.
getOpcode() == ARMISD::CSINC &&
14824 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
14825 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
14828 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
14830 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
14843 SDValue InDouble =
N->getOperand(0);
14844 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
14858 SDValue BasePtr = LD->getBasePtr();
14860 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
14861 LD->getAlign(), LD->getMemOperand()->getFlags());
14867 LD->getPointerInfo().getWithOffset(4),
14869 LD->getMemOperand()->getFlags());
14885 bool BVSwap = BV.
getOpcode() == ISD::BITCAST;
14888 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
14890 BVSwap = BV.
getOpcode() == ISD::BITCAST;
14902 if (!Subtarget->
isLittle() && BVSwap)
14920 if (!Subtarget->
isLittle() && BVSwap)
14939 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
14952 if (Op0->
getOpcode() == ARMISD::VMOVrh)
14963 if (Op0->
getOpcode() == ISD::BITCAST) {
14965 if (Copy.getValueType() == MVT::f32 &&
14967 bool HasGlue = Copy->getNumOperands() == 3;
14968 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
14969 HasGlue ? Copy->getOperand(2) :
SDValue()};
14970 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
14989 if (LN0->hasOneUse() && LN0->isUnindexed() &&
14990 LN0->getMemoryVT() == MVT::i16) {
14993 LN0->getBasePtr(), LN0->getMemOperand());
15011 EVT VT =
N->getValueType(0);
15045 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15046 for (
unsigned i = 0; i < NumElts; ++i) {
15047 SDNode *Elt =
N->getOperand(i).getNode();
15064 if (
N->getNumOperands() == 2)
15070 EVT VT =
N->getValueType(0);
15076 for (
unsigned i = 0; i < NumElts; ++i) {
15077 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(i));
15084 return DAG.
getNode(ISD::BITCAST, dl, VT, BV);
15102 EVT VT =
N->getValueType(0);
15110 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15114 if (
Use->getOpcode() != ISD::BITCAST ||
15115 Use->getValueType(0).isFloatingPoint())
15123 unsigned NumOfBitCastedElts = 0;
15125 unsigned NumOfRelevantElts = NumElts;
15126 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15128 if (Elt->
getOpcode() == ISD::BITCAST) {
15131 ++NumOfBitCastedElts;
15135 --NumOfRelevantElts;
15139 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15157 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15161 if (V.getOpcode() == ISD::BITCAST &&
15162 V->getOperand(0).getValueType() == MVT::i32)
15164 V = V.getOperand(0);
15173 Vec = DAG.
getNode(ISD::BITCAST, dl, VT, Vec);
15181 EVT VT =
N->getValueType(0);
15186 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15188 if (
Op->getOperand(0).getValueType() == VT)
15189 return Op->getOperand(0);
15190 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15197 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15204 if (
Op.getValueType() == MVT::i32) {
15215 EVT VT =
N->getValueType(0);
15220 if (ST->isLittle())
15221 return DAG.
getNode(ISD::BITCAST, dl, VT,
Op);
15224 if (
Op.getValueType() == VT)
15231 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15233 if (
Op->getOperand(0).getValueType() == VT)
15234 return Op->getOperand(0);
15235 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15243 if (!Subtarget->hasMVEIntegerOps())
15246 EVT VT =
N->getValueType(0);
15254 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15260 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15264 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15277 EVT VT =
N->getValueType(0);
15278 SDNode *Elt =
N->getOperand(1).getNode();
15287 SDValue Vec = DAG.
getNode(ISD::BITCAST, dl, FloatVT,
N->getOperand(0));
15288 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(1));
15293 Vec, V,
N->getOperand(2));
15294 return DAG.
getNode(ISD::BITCAST, dl, VT, InsElt);
15303 EVT VT =
N->getValueType(0);
15311 if (Ext.getOpcode() == ISD::BITCAST &&
15312 Ext.getOperand(0).getValueType() == MVT::f32)
15313 Ext = Ext.getOperand(0);
15316 Ext.getConstantOperandVal(1) % 2 != 0)
15318 if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() ==
ISD::SINT_TO_FP ||
15322 SDValue Op0 = Ext.getOperand(0);
15325 unsigned Lane = Ext.getConstantOperandVal(1);
15331 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15332 isa<ConstantSDNode>(V->getOperand(1)) &&
15333 V->getConstantOperandVal(1) == Lane + 1 &&
15334 V->getOperand(0).getResNo() == ResNo;
15336 if (OtherIt == Op0->
users().
end())
15341 SDValue OtherExt(*OtherIt, 0);
15353 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15354 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15356 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15366 EVT VT =
N->getValueType(0);
15370 if (Op0->
getOpcode() == ARMISD::VDUP) {
15372 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15373 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15374 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15375 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15376 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15379 while (
X.getValueType() != VT &&
X->getOpcode() == ISD::BITCAST)
15380 X =
X->getOperand(0);
15381 if (
X.getValueType() == VT)
15389 return Op0.
getOperand(
N->getConstantOperandVal(1));
15399 unsigned Offset =
N->getConstantOperandVal(1);
15401 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15411 unsigned Idx =
N->getConstantOperandVal(1);
15425 EVT VT =
N->getValueType(0);
15428 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15430 Op.getOperand(0).getValueType().getScalarType())
15431 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15440 SDValue SubVec =
N->getOperand(1);
15441 uint64_t IdxVal =
N->getConstantOperandVal(2);
15452 if (IdxVal == 0 && Vec.
isUndef())
15458 (IdxVal != 0 && IdxVal != NumSubElts))
15489 ARMISD::VMOVN,
DL, VT,
15495 ARMISD::VMOVN,
DL, VT,
15531 EVT VT =
N->getValueType(0);
15542 unsigned HalfElts = NumElts/2;
15544 for (
unsigned n = 0; n < NumElts; ++n) {
15547 if (MaskElt < (
int)HalfElts)
15549 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15550 NewElt = HalfElts + MaskElt - NumElts;
15593 bool SimpleConstIncOnly,
15601 bool isLoadOp =
true;
15602 bool isLaneOp =
false;
15605 bool hasAlignment =
true;
15606 unsigned NewOpc = 0;
15607 unsigned NumVecs = 0;
15608 if (
Target.isIntrinsic) {
15609 unsigned IntNo =
N->getConstantOperandVal(1);
15613 case Intrinsic::arm_neon_vld1:
15617 case Intrinsic::arm_neon_vld2:
15621 case Intrinsic::arm_neon_vld3:
15625 case Intrinsic::arm_neon_vld4:
15629 case Intrinsic::arm_neon_vld1x2:
15632 hasAlignment =
false;
15634 case Intrinsic::arm_neon_vld1x3:
15637 hasAlignment =
false;
15639 case Intrinsic::arm_neon_vld1x4:
15642 hasAlignment =
false;
15644 case Intrinsic::arm_neon_vld2dup:
15648 case Intrinsic::arm_neon_vld3dup:
15652 case Intrinsic::arm_neon_vld4dup:
15656 case Intrinsic::arm_neon_vld2lane:
15661 case Intrinsic::arm_neon_vld3lane:
15666 case Intrinsic::arm_neon_vld4lane:
15671 case Intrinsic::arm_neon_vst1:
15676 case Intrinsic::arm_neon_vst2:
15677 NewOpc = ARMISD::VST2_UPD;
15681 case Intrinsic::arm_neon_vst3:
15686 case Intrinsic::arm_neon_vst4:
15687 NewOpc = ARMISD::VST4_UPD;
15691 case Intrinsic::arm_neon_vst2lane:
15697 case Intrinsic::arm_neon_vst3lane:
15703 case Intrinsic::arm_neon_vst4lane:
15709 case Intrinsic::arm_neon_vst1x2:
15713 hasAlignment =
false;
15715 case Intrinsic::arm_neon_vst1x3:
15719 hasAlignment =
false;
15721 case Intrinsic::arm_neon_vst1x4:
15725 hasAlignment =
false;
15730 switch (
N->getOpcode()) {
15766 VecTy =
N->getValueType(0);
15767 }
else if (
Target.isIntrinsic) {
15768 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
15771 "Node has to be a load, a store, or an intrinsic!");
15772 VecTy =
N->getOperand(1).getValueType();
15780 if (isLaneOp || isVLDDUPOp)
15783 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
15789 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
15798 EVT AlignedVecTy = VecTy;
15818 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
15819 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
15830 Alignment =
Align(1);
15836 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
15838 for (n = 0; n < NumResultVecs; ++n)
15839 Tys[n] = AlignedVecTy;
15840 Tys[n++] = MVT::i32;
15841 Tys[n] = MVT::Other;
15846 Ops.push_back(
N->getOperand(0));
15847 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
15852 Ops.push_back(StN->getValue());
15856 unsigned LastOperand =
15857 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
15858 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
15859 Ops.push_back(
N->getOperand(i));
15867 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::STORE) {
15869 StVal = DAG.
getNode(ISD::BITCAST, dl, AlignedVecTy, StVal);
15878 for (
unsigned i = 0; i < NumResultVecs; ++i)
15883 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::LOAD) {
15884 SDValue &LdVal = NewResults[0];
15885 LdVal = DAG.
getNode(ISD::BITCAST, dl, VecTy, LdVal);
15920 switch (
N->getOpcode()) {
15924 *Ptr =
N->getOperand(0);
15925 *CInc =
N->getOperand(1);
15932 *Ptr =
N->getOperand(1);
15933 *CInc =
N->getOperand(2);
15952 const bool isStore =
N->getOpcode() == ISD::STORE;
15960 SDValue Addr =
N->getOperand(AddrOpIdx);
15971 unsigned ConstInc =
15976 if (BaseUpdates.
size() >= MaxBaseUpdates)
15996 unsigned UserOffset =
15999 if (!UserOffset || UserOffset <=
Offset)
16002 unsigned NewConstInc = UserOffset -
Offset;
16005 if (BaseUpdates.
size() >= MaxBaseUpdates)
16012 unsigned NumValidUpd = BaseUpdates.
size();
16013 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16024 return LHS.ConstInc <
RHS.ConstInc;
16053 unsigned IntNo =
N->getConstantOperandVal(1);
16054 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16056 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16079 bool isLoadOp =
true;
16080 unsigned NewOpc = 0;
16081 unsigned NumVecs = 0;
16085 case Intrinsic::arm_mve_vld2q:
16089 case Intrinsic::arm_mve_vld4q:
16093 case Intrinsic::arm_mve_vst2q:
16094 NewOpc = ARMISD::VST2_UPD;
16098 case Intrinsic::arm_mve_vst4q:
16099 NewOpc = ARMISD::VST4_UPD;
16108 VecTy =
N->getValueType(0);
16110 VecTy =
N->getOperand(3).getValueType();
16124 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16126 for (n = 0; n < NumResultVecs; ++n)
16128 Tys[n++] = MVT::i32;
16129 Tys[n] = MVT::Other;
16134 Ops.push_back(
N->getOperand(0));
16135 Ops.push_back(
N->getOperand(2));
16136 Ops.push_back(Inc);
16138 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16139 Ops.push_back(
N->getOperand(i));
16146 for (
unsigned i = 0; i < NumResultVecs; ++i)
16165 EVT VT =
N->getValueType(0);
16171 SDNode *VLD =
N->getOperand(0).getNode();
16174 unsigned NumVecs = 0;
16175 unsigned NewOpc = 0;
16177 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16180 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16183 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16195 if (
Use.getResNo() == NumVecs)
16198 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16199 VLDLaneNo !=
User->getConstantOperandVal(1))
16206 for (n = 0; n < NumVecs; ++n)
16208 Tys[n] = MVT::Other;
16218 unsigned ResNo =
Use.getResNo();
16220 if (ResNo == NumVecs)
16227 std::vector<SDValue> VLDDupResults;
16228 for (
unsigned n = 0; n < NumVecs; ++n)
16242 EVT VT =
N->getValueType(0);
16245 if (Subtarget->hasMVEIntegerOps()) {
16249 ExtractVT = MVT::i32;
16251 N->getOperand(0),
N->getOperand(1));
16262 while (
Op.getOpcode() == ISD::BITCAST)
16263 Op =
Op.getOperand(0);
16264 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16268 unsigned EltSize =
Op.getScalarValueSizeInBits();
16270 unsigned Imm =
Op.getConstantOperandVal(0);
16286 if (Subtarget->hasMVEIntegerOps()) {
16289 if (
Op.getValueType() == MVT::f32)
16290 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16291 DAG.
getNode(ISD::BITCAST, dl, MVT::i32,
Op));
16292 else if (
Op.getValueType() == MVT::f16)
16293 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16294 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16297 if (!Subtarget->hasNEON())
16304 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16305 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16306 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16311 LD->getMemoryVT(), LD->getMemOperand());
16322 EVT VT =
N->getValueType(0);
16344 assert(StVT != VT &&
"Cannot truncate to the same type");
16354 if (0 != (NumElems * FromEltSz) % ToEltSz)
16357 unsigned SizeRatio = FromEltSz / ToEltSz;
16362 NumElems * SizeRatio);
16368 for (
unsigned i = 0; i < NumElems; ++i)
16382 MVT StoreType = MVT::i8;
16384 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16404 for (
unsigned I = 0;
I <
E;
I++) {
16435 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16438 unsigned NumElements = 4;
16455 unsigned Off0 = Rev ? NumElts : 0;
16456 unsigned Off1 = Rev ? 0 : NumElts;
16458 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16459 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16461 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16469 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16489 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16500 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16504 NewToVT, Alignment, MMOFlags, AAInfo);
16537 unsigned NewOffset =
16545 NewToVT, Alignment, MMOFlags, AAInfo);
16567 {Extract.getOperand(0), Extract.getOperand(1)});
16598 if (Subtarget->hasNEON())
16602 if (Subtarget->hasMVEFloatOps())
16606 if (Subtarget->hasMVEIntegerOps()) {
16681 if (!Subtarget->hasNEON())
16685 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16693 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16695 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16696 uint32_t IntBits = IntTy.getSizeInBits();
16697 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16698 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16709 if (
C == -1 ||
C == 0 ||
C > 32)
16714 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16715 Intrinsic::arm_neon_vcvtfp2fxu;
16718 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16721 if (IntBits < FloatBits)
16729 if (!Subtarget->hasMVEFloatOps())
16737 EVT VT =
N->getValueType(0);
16742 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16743 if (
Op.getOpcode() != ISD::BITCAST ||
16744 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
16746 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16747 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16749 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16762 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
16773 EVT VT =
N->getValueType(0);
16776 if (!
N->getFlags().hasAllowReassociation())
16783 unsigned Opc =
A.getConstantOperandVal(0);
16784 if (
Opc != Intrinsic::arm_mve_vcmlaq)
16789 A.getOperand(3),
A.getOperand(4));
16821 if (!Subtarget->hasNEON())
16825 unsigned OpOpcode =
Op.getNode()->getOpcode();
16826 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
16830 SDValue ConstVec =
N->getOperand(1);
16834 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
16836 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
16837 uint32_t IntBits = IntTy.getSizeInBits();
16838 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16839 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16859 int32_t
C = IntVal.exactLogBase2();
16860 if (
C == -1 ||
C == 0 ||
C > 32)
16866 if (IntBits < FloatBits)
16868 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
16870 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
16871 : Intrinsic::arm_neon_vcvtfxu2fp;
16879 if (!ST->hasMVEIntegerOps())
16882 assert(
N->getOpcode() == ISD::VECREDUCE_ADD);
16883 EVT ResVT =
N->getValueType(0);
16911 EVT AVT =
A.getValueType();
16917 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
16918 EVT AVT =
A.getValueType();
16926 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
16927 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
16930 if (ExtTypeMatches(
A, ExtTypes))
16931 return ExtendIfNeeded(
A, ExtendCode);
16934 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
16941 if (Ext->getOpcode() != ExtendCode)
16944 if (ExtTypeMatches(
A, ExtTypes))
16945 return ExtendIfNeeded(
A, ExtendCode);
16948 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
16958 if (ResVT != RetTy)
16961 if (
Mul->getOpcode() == ExtendCode &&
16962 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
16964 Mul =
Mul->getOperand(0);
16973 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
16974 A = ExtendIfNeeded(
A, ExtendCode);
16975 B = ExtendIfNeeded(
B, ExtendCode);
16980 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
16993 if (
Mul->getOpcode() == ExtendCode &&
16994 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
16996 Mul =
Mul->getOperand(0);
17005 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17006 A = ExtendIfNeeded(
A, ExtendCode);
17007 B = ExtendIfNeeded(
B, ExtendCode);
17018 EVT VT =
Ops[0].getValueType();
17019 if (VT == MVT::v16i8) {
17020 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17021 "Unexpected illegal long reduction opcode");
17022 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17034 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17047 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17049 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17050 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17052 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17053 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17055 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17058 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17061 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17065 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17068 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17071 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17074 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17077 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17080 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17083 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17085 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17087 return Create64bitNode(ARMISD::VADDLVs, {
A});
17089 return Create64bitNode(ARMISD::VADDLVu, {
A});
17092 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17095 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17098 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17100 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17102 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17104 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17107 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17110 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17117 Op =
Op->getOperand(1);
17119 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17121 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17127 return DAG.
getNode(ISD::VECREDUCE_ADD, dl, ResVT, Ext);
17138 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17140 if (!Shuf || !Shuf->getOperand(1).isUndef())
17145 APInt SetElts(Mask.size(), 0);
17146 for (
int E : Mask) {
17154 if (
N->getNumOperands() != VecOp + 1) {
17156 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17162 if (
Op.getValueType().isVector())
17163 Ops.push_back(
Op.getOperand(0));
17174 unsigned IsTop =
N->getConstantOperandVal(2);
17181 if (Op0->
isUndef() && !IsTop)
17186 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17187 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17195 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17197 APInt Op0DemandedElts =
17198 IsTop ? Op1DemandedElts
17213 unsigned IsTop =
N->getConstantOperandVal(2);
17215 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17216 APInt Op0DemandedElts =
17228 EVT VT =
N->getValueType(0);
17235 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17236 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17240 LHS.getOperand(0),
RHS.getOperand(0));
17255 int ShiftAmt =
C->getSExtValue();
17256 if (ShiftAmt == 0) {
17262 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17263 unsigned NewOpcode =
17264 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17279 unsigned IntNo =
N->getConstantOperandVal(0);
17290 case Intrinsic::arm_neon_vshifts:
17291 case Intrinsic::arm_neon_vshiftu:
17292 case Intrinsic::arm_neon_vrshifts:
17293 case Intrinsic::arm_neon_vrshiftu:
17294 case Intrinsic::arm_neon_vrshiftn:
17295 case Intrinsic::arm_neon_vqshifts:
17296 case Intrinsic::arm_neon_vqshiftu:
17297 case Intrinsic::arm_neon_vqshiftsu:
17298 case Intrinsic::arm_neon_vqshiftns:
17299 case Intrinsic::arm_neon_vqshiftnu:
17300 case Intrinsic::arm_neon_vqshiftnsu:
17301 case Intrinsic::arm_neon_vqrshiftns:
17302 case Intrinsic::arm_neon_vqrshiftnu:
17303 case Intrinsic::arm_neon_vqrshiftnsu: {
17304 EVT VT =
N->getOperand(1).getValueType();
17306 unsigned VShiftOpc = 0;
17309 case Intrinsic::arm_neon_vshifts:
17310 case Intrinsic::arm_neon_vshiftu:
17312 VShiftOpc = ARMISD::VSHLIMM;
17315 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17316 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17317 : ARMISD::VSHRuIMM);
17322 case Intrinsic::arm_neon_vrshifts:
17323 case Intrinsic::arm_neon_vrshiftu:
17328 case Intrinsic::arm_neon_vqshifts:
17329 case Intrinsic::arm_neon_vqshiftu:
17334 case Intrinsic::arm_neon_vqshiftsu:
17339 case Intrinsic::arm_neon_vrshiftn:
17340 case Intrinsic::arm_neon_vqshiftns:
17341 case Intrinsic::arm_neon_vqshiftnu:
17342 case Intrinsic::arm_neon_vqshiftnsu:
17343 case Intrinsic::arm_neon_vqrshiftns:
17344 case Intrinsic::arm_neon_vqrshiftnu:
17345 case Intrinsic::arm_neon_vqrshiftnsu:
17357 case Intrinsic::arm_neon_vshifts:
17358 case Intrinsic::arm_neon_vshiftu:
17361 case Intrinsic::arm_neon_vrshifts:
17362 VShiftOpc = ARMISD::VRSHRsIMM;
17364 case Intrinsic::arm_neon_vrshiftu:
17365 VShiftOpc = ARMISD::VRSHRuIMM;
17367 case Intrinsic::arm_neon_vrshiftn:
17368 VShiftOpc = ARMISD::VRSHRNIMM;
17370 case Intrinsic::arm_neon_vqshifts:
17371 VShiftOpc = ARMISD::VQSHLsIMM;
17373 case Intrinsic::arm_neon_vqshiftu:
17374 VShiftOpc = ARMISD::VQSHLuIMM;
17376 case Intrinsic::arm_neon_vqshiftsu:
17377 VShiftOpc = ARMISD::VQSHLsuIMM;
17379 case Intrinsic::arm_neon_vqshiftns:
17380 VShiftOpc = ARMISD::VQSHRNsIMM;
17382 case Intrinsic::arm_neon_vqshiftnu:
17383 VShiftOpc = ARMISD::VQSHRNuIMM;
17385 case Intrinsic::arm_neon_vqshiftnsu:
17386 VShiftOpc = ARMISD::VQSHRNsuIMM;
17388 case Intrinsic::arm_neon_vqrshiftns:
17389 VShiftOpc = ARMISD::VQRSHRNsIMM;
17391 case Intrinsic::arm_neon_vqrshiftnu:
17392 VShiftOpc = ARMISD::VQRSHRNuIMM;
17394 case Intrinsic::arm_neon_vqrshiftnsu:
17395 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17400 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17401 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17404 case Intrinsic::arm_neon_vshiftins: {
17405 EVT VT =
N->getOperand(1).getValueType();
17407 unsigned VShiftOpc = 0;
17410 VShiftOpc = ARMISD::VSLIIMM;
17411 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17412 VShiftOpc = ARMISD::VSRIIMM;
17418 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17419 N->getOperand(1),
N->getOperand(2),
17423 case Intrinsic::arm_neon_vqrshifts:
17424 case Intrinsic::arm_neon_vqrshiftu:
17428 case Intrinsic::arm_neon_vbsl: {
17430 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17431 N->getOperand(2),
N->getOperand(3));
17433 case Intrinsic::arm_mve_vqdmlah:
17434 case Intrinsic::arm_mve_vqdmlash:
17435 case Intrinsic::arm_mve_vqrdmlah:
17436 case Intrinsic::arm_mve_vqrdmlash:
17437 case Intrinsic::arm_mve_vmla_n_predicated:
17438 case Intrinsic::arm_mve_vmlas_n_predicated:
17439 case Intrinsic::arm_mve_vqdmlah_predicated:
17440 case Intrinsic::arm_mve_vqdmlash_predicated:
17441 case Intrinsic::arm_mve_vqrdmlah_predicated:
17442 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17447 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17454 case Intrinsic::arm_mve_minv:
17455 case Intrinsic::arm_mve_maxv:
17456 case Intrinsic::arm_mve_minav:
17457 case Intrinsic::arm_mve_maxav:
17458 case Intrinsic::arm_mve_minv_predicated:
17459 case Intrinsic::arm_mve_maxv_predicated:
17460 case Intrinsic::arm_mve_minav_predicated:
17461 case Intrinsic::arm_mve_maxav_predicated: {
17464 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17471 case Intrinsic::arm_mve_addv: {
17474 bool Unsigned =
N->getConstantOperandVal(2);
17475 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17479 case Intrinsic::arm_mve_addlv:
17480 case Intrinsic::arm_mve_addlv_predicated: {
17483 bool Unsigned =
N->getConstantOperandVal(2);
17484 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17485 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17486 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17489 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17491 Ops.push_back(
N->getOperand(i));
17512 EVT VT =
N->getValueType(0);
17514 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17515 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17516 N->getOperand(0)->hasOneUse()) {
17533 if (AndMask == 255 || AndMask == 65535)
17537 if (MaskedBits > ShiftAmt) {
17552 if (ST->hasMVEIntegerOps())
17557 switch (
N->getOpcode()) {
17563 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17570 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17571 unsigned VShiftOpc =
17572 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17574 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17590 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17593 EVT FromVT = LD->getValueType(0);
17594 EVT ToVT =
N->getValueType(0);
17601 unsigned NumElements = 0;
17602 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17604 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17606 if (NumElements == 0 ||
17616 SDValue BasePtr = LD->getBasePtr();
17617 Align Alignment = LD->getBaseAlign();
17638 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17639 Alignment, MMOFlags, AAInfo);
17645 if (FromEltVT == MVT::f16) {
17648 for (
unsigned i = 0; i < Loads.
size(); i++) {
17650 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
17674 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17678 EVT VT =
N->getValueType(0);
17682 if (VT == MVT::i32 &&
17683 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17688 switch (
N->getOpcode()) {
17691 Opc = ARMISD::VGETLANEs;
17695 Opc = ARMISD::VGETLANEu;
17702 if (ST->hasMVEIntegerOps())
17711 if (ST->hasMVEFloatOps())
17722 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17726 EVT VT =
Op.getValueType();
17729 if (VT != MVT::i32 ||
17742 APInt MaxC = Max.getConstantOperandAPInt(1);
17745 !(MinC + 1).isPowerOf2())
17763 EVT VT =
N->getValueType(0);
17766 if (VT == MVT::i32)
17769 if (!ST->hasMVEIntegerOps())
17775 if (VT != MVT::v4i32 && VT != MVT::v8i16)
17778 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
17786 if (VT == MVT::v4i32)
17787 SaturateC =
APInt(32, (1 << 15) - 1,
true);
17789 SaturateC =
APInt(16, (1 << 7) - 1,
true);
17796 MaxC != ~SaturateC)
17801 if (IsSignedSaturate(
N, N0.
getNode())) {
17804 if (VT == MVT::v4i32) {
17805 HalfVT = MVT::v8i16;
17806 ExtVT = MVT::v4i16;
17808 HalfVT = MVT::v16i8;
17823 auto IsUnsignedSaturate = [&](
SDNode *Min) {
17829 if (VT == MVT::v4i32)
17830 SaturateC =
APInt(32, (1 << 16) - 1,
true);
17832 SaturateC =
APInt(16, (1 << 8) - 1,
true);
17841 if (IsUnsignedSaturate(
N)) {
17845 if (VT == MVT::v4i32) {
17846 HalfVT = MVT::v8i16;
17847 ExtConst = 0x0000FFFF;
17849 HalfVT = MVT::v16i8;
17871 const APInt *CV = &
C->getAPIntValue();
17889 SDValue Op0 = CMOV->getOperand(0);
17890 SDValue Op1 = CMOV->getOperand(1);
17891 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
17892 SDValue CmpZ = CMOV->getOperand(3);
17928 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
17935 if ((OrCI & Known.
Zero) != OrCI)
17941 EVT VT =
X.getValueType();
17942 unsigned BitInX = AndC->
logBase2();
17950 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
17951 BitInY < NumActiveBits; ++BitInY) {
17952 if (OrCI[BitInY] == 0)
17955 Mask.setBit(BitInY);
17956 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
17972 switch (
N->getOpcode()) {
17987 if (Const->isZero())
17989 else if (Const->isOne())
17997 unsigned IntOp =
N.getConstantOperandVal(1);
17998 if (IntOp != Intrinsic::test_start_loop_iterations &&
17999 IntOp != Intrinsic::loop_decrement_reg)
18025 bool Negate =
false;
18029 if (
N->getOpcode() == ISD::BRCOND) {
18031 Cond =
N->getOperand(1);
18032 Dest =
N->getOperand(2);
18034 assert(
N->getOpcode() == ISD::BR_CC &&
"Expected BRCOND or BR_CC!");
18036 Cond =
N->getOperand(2);
18037 Dest =
N->getOperand(4);
18039 if (!Const->isOne() && !Const->isZero())
18041 Imm = Const->getZExtValue();
18069 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18070 "unsupported condition");
18075 unsigned IntOp =
Int->getConstantOperandVal(1);
18076 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() == ISD::BR) &&
18077 "expected single br user");
18078 SDNode *Br = *
N->user_begin();
18088 if (IntOp == Intrinsic::test_start_loop_iterations) {
18090 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18092 if (IsTrueIfZero(CC, Imm)) {
18094 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18098 UpdateUncondBr(Br, Dest, DAG);
18100 SDValue Ops[] = {Chain, Setup, OtherTarget};
18101 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18113 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18117 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18121 if (
Target == OtherTarget)
18122 UpdateUncondBr(Br, Dest, DAG);
18128 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18137 if (Cmp.getOpcode() != ARMISD::CMPZ)
18142 SDValue LHS = Cmp.getOperand(0);
18143 SDValue RHS = Cmp.getOperand(1);
18152 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18153 LHS->getOperand(0)->hasOneUse() &&
18157 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18169 if (Cmp.getOpcode() != ARMISD::CMPZ)
18173 EVT VT =
N->getValueType(0);
18175 SDValue LHS = Cmp.getOperand(0);
18176 SDValue RHS = Cmp.getOperand(1);
18177 SDValue FalseVal =
N->getOperand(0);
18178 SDValue TrueVal =
N->getOperand(1);
18183 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18207 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18208 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18209 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18212 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18217 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18220 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18221 LHS->getOperand(2), LHS->getOperand(3));
18231 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18235 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18237 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18246 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18279 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18291 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18311 const APInt *TrueConst;
18312 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18313 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18314 FalseVal.getOperand(1) == RHS) ||
18318 unsigned ShiftAmount = TrueConst->
logBase2();
18333 if (Known.
Zero == 0xfffffffe)
18336 else if (Known.
Zero == 0xffffff00)
18339 else if (Known.
Zero == 0xffff0000)
18352 EVT DstVT =
N->getValueType(0);
18355 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18356 EVT SrcVT = Src.getValueType();
18358 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18363 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18364 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18365 Src.getValueType().getScalarSizeInBits())
18366 Src = Src.getOperand(0);
18370 EVT SrcVT = Src.getValueType();
18371 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18372 Src.getOpcode() == ARMISD::VMVNIMM ||
18373 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18376 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18390 EVT VT =
N->getValueType(0);
18398 if (
N->getNumOperands() == 2 &&
18402 N->getOperand(0).getOperand(1),
18403 N->getOperand(1).getOperand(0),
18404 N->getOperand(1).getOperand(1));
18407 if (
N->getNumOperands() == 2 &&
18413 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18414 S0->getOperand(1) ==
S1->getOperand(1)) {
18417 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18421 ARMISD::VMOVN,
DL, VT,
18422 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18423 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18427 ARMISD::VMOVN,
DL, VT,
18428 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18429 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18437 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18438 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18439 (Op.getOpcode() == ISD::BITCAST &&
18440 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18443 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18445 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18463 int NumIns =
N->getNumOperands();
18464 assert((NumIns == 2 || NumIns == 4) &&
18465 "Expected 2 or 4 inputs to an MVETrunc");
18467 if (
N->getNumOperands() == 4)
18471 for (
int I = 0;
I < NumIns;
I++) {
18473 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18478 Ptr, MPI, StoreVT,
Align(4));
18493 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18496 EVT FromVT = LD->getMemoryVT();
18497 EVT ToVT =
N->getValueType(0);
18504 unsigned NumElements = 0;
18505 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18507 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18509 assert(NumElements != 0);
18515 LD->getExtensionType() != NewExtType)
18522 SDValue BasePtr = LD->getBasePtr();
18523 Align Alignment = LD->getBaseAlign();
18542 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18543 Alignment, MMOFlags, AAInfo);
18559 EVT VT =
N->getValueType(0);
18561 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18562 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18564 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18566 auto Extend = [&](
SDValue V) {
18575 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
18576 SDValue Ext = Extend(
N->getOperand(0));
18584 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18585 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
18589 auto CheckInregMask = [&](
int Start,
int Offset) {
18591 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18597 if (CheckInregMask(0, 0))
18599 else if (CheckInregMask(0, 1))
18600 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18601 else if (CheckInregMask(0, Mask.size()))
18603 else if (CheckInregMask(0, Mask.size() + 1))
18604 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18609 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18613 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18620 if (
N->getOperand(0)->getOpcode() == ISD::LOAD)
18631 int NumOuts =
N->getNumValues();
18632 assert((NumOuts == 2 || NumOuts == 4) &&
18633 "Expected 2 or 4 outputs to an MVEEXT");
18634 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18636 if (
N->getNumOperands() == 4)
18642 StackPtr, MPI,
Align(4));
18645 for (
int I = 0;
I < NumOuts;
I++) {
18647 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18648 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18653 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
18662 switch (
N->getOpcode()) {
18713 case ISD::FP_EXTEND:
18722 case ARMISD::BRCOND:
18726 case ARMISD::CSINC:
18727 case ARMISD::CSINV:
18728 case ARMISD::CSNEG:
18741 case ARMISD::PREDICATE_CAST:
18743 case ARMISD::VECTOR_REG_CAST:
18752 case ISD::VECREDUCE_ADD:
18754 case ARMISD::VADDVs:
18755 case ARMISD::VADDVu:
18756 case ARMISD::VADDLVs:
18757 case ARMISD::VADDLVu:
18758 case ARMISD::VADDLVAs:
18759 case ARMISD::VADDLVAu:
18760 case ARMISD::VMLAVs:
18761 case ARMISD::VMLAVu:
18762 case ARMISD::VMLALVs:
18763 case ARMISD::VMLALVu:
18764 case ARMISD::VMLALVAs:
18765 case ARMISD::VMLALVAu:
18767 case ARMISD::VMOVN:
18769 case ARMISD::VQMOVNs:
18770 case ARMISD::VQMOVNu:
18772 case ARMISD::VQDMULH:
18778 case ARMISD::SMULWB: {
18779 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18785 case ARMISD::SMULWT: {
18786 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18792 case ARMISD::SMLALBB:
18793 case ARMISD::QADD16b:
18794 case ARMISD::QSUB16b:
18795 case ARMISD::UQADD16b:
18796 case ARMISD::UQSUB16b: {
18797 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18804 case ARMISD::SMLALBT: {
18805 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
18807 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
18814 case ARMISD::SMLALTB: {
18815 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
18817 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
18824 case ARMISD::SMLALTT: {
18825 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18832 case ARMISD::QADD8b:
18833 case ARMISD::QSUB8b:
18834 case ARMISD::UQADD8b:
18835 case ARMISD::UQSUB8b: {
18836 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18844 if (
N->getOperand(1) ==
N->getOperand(2))
18845 return N->getOperand(1);
18849 switch (
N->getConstantOperandVal(1)) {
18850 case Intrinsic::arm_neon_vld1:
18851 case Intrinsic::arm_neon_vld1x2:
18852 case Intrinsic::arm_neon_vld1x3:
18853 case Intrinsic::arm_neon_vld1x4:
18854 case Intrinsic::arm_neon_vld2:
18855 case Intrinsic::arm_neon_vld3:
18856 case Intrinsic::arm_neon_vld4:
18857 case Intrinsic::arm_neon_vld2lane:
18858 case Intrinsic::arm_neon_vld3lane:
18859 case Intrinsic::arm_neon_vld4lane:
18860 case Intrinsic::arm_neon_vld2dup:
18861 case Intrinsic::arm_neon_vld3dup:
18862 case Intrinsic::arm_neon_vld4dup:
18863 case Intrinsic::arm_neon_vst1:
18864 case Intrinsic::arm_neon_vst1x2:
18865 case Intrinsic::arm_neon_vst1x3:
18866 case Intrinsic::arm_neon_vst1x4:
18867 case Intrinsic::arm_neon_vst2:
18868 case Intrinsic::arm_neon_vst3:
18869 case Intrinsic::arm_neon_vst4:
18870 case Intrinsic::arm_neon_vst2lane:
18871 case Intrinsic::arm_neon_vst3lane:
18872 case Intrinsic::arm_neon_vst4lane:
18874 case Intrinsic::arm_mve_vld2q:
18875 case Intrinsic::arm_mve_vld4q:
18876 case Intrinsic::arm_mve_vst2q:
18877 case Intrinsic::arm_mve_vst4q:
18888 return (VT == MVT::f32) && (
Opc == ISD::LOAD ||
Opc == ISD::STORE);
18894 unsigned *
Fast)
const {
18900 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
18903 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
18905 if (AllowsUnaligned) {
18907 *
Fast = Subtarget->hasV7Ops();
18912 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
18916 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
18923 if (!Subtarget->hasMVEIntegerOps())
18927 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
18928 Ty == MVT::v2i1)) {
18936 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
18952 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
18953 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
18954 Ty == MVT::v2f64) {
18965 const AttributeList &FuncAttributes)
const {
18967 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
18968 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
18970 if (
Op.size() >= 16 &&
18976 }
else if (
Op.size() >= 8 &&
18993 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
18995 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
18997 return (SrcBits == 64 && DestBits == 32);
19006 return (SrcBits == 64 && DestBits == 32);
19042 return Subtarget->hasFullFP16();
19049 if (!Subtarget->hasMVEIntegerOps())
19068 if (Ld->isExpandingLoad())
19072 if (Subtarget->hasMVEIntegerOps())
19085 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19117bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19119 if (Subtarget->useSoftFloat())
19128 return Subtarget->hasMVEFloatOps();
19146 unsigned Scale = 1;
19163 if ((V & (Scale - 1)) != 0)
19172 if (VT.
isVector() && Subtarget->hasNEON())
19175 !Subtarget->hasMVEFloatOps())
19178 bool IsNeg =
false;
19184 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19187 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19203 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19209 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19239 default:
return false;
19258 int Scale = AM.
Scale;
19263 default:
return false;
19271 Scale = Scale & ~1;
19272 return Scale == 2 || Scale == 4 || Scale == 8;
19289 if (Scale & 1)
return false;
19296 const int Scale = AM.
Scale;
19306 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19322 switch (AM.
Scale) {
19333 if (Subtarget->isThumb1Only())
19336 if (Subtarget->isThumb2())
19339 int Scale = AM.
Scale;
19341 default:
return false;
19345 if (Scale < 0) Scale = -Scale;
19353 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19366 if (Scale & 1)
return false;
19379 if (!Subtarget->isThumb())
19382 if (Subtarget->isThumb2())
19386 return Imm >= 0 && Imm <= 255;
19396 if (!Subtarget->isThumb())
19398 if (Subtarget->isThumb2())
19401 return AbsImm <= 255;
19436 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19440 int RHSC = (int)
RHS->getZExtValue();
19441 if (RHSC < 0 && RHSC > -256) {
19451 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19454 int RHSC = (int)
RHS->getZExtValue();
19455 if (RHSC < 0 && RHSC > -0x1000) {
19497 int RHSC = (int)
RHS->getZExtValue();
19498 if (RHSC < 0 && RHSC > -0x100) {
19503 }
else if (RHSC > 0 && RHSC < 0x100) {
19514 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19525 bool CanChangeType = isLE && !IsMasked;
19528 int RHSC = (int)
RHS->getZExtValue();
19530 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19531 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19536 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19547 if (VT == MVT::v4i16) {
19548 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19550 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19551 if (IsInRange(RHSC, 0x80, 1))
19553 }
else if (Alignment >= 4 &&
19554 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19555 IsInRange(RHSC, 0x80, 4))
19557 else if (Alignment >= 2 &&
19558 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19559 IsInRange(RHSC, 0x80, 2))
19561 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19574 if (Subtarget->isThumb1Only())
19580 bool isSEXTLoad =
false;
19581 bool IsMasked =
false;
19583 Ptr = LD->getBasePtr();
19584 VT = LD->getMemoryVT();
19585 Alignment = LD->getAlign();
19588 Ptr = ST->getBasePtr();
19589 VT = ST->getMemoryVT();
19590 Alignment = ST->getAlign();
19592 Ptr = LD->getBasePtr();
19593 VT = LD->getMemoryVT();
19594 Alignment = LD->getAlign();
19598 Ptr = ST->getBasePtr();
19599 VT = ST->getMemoryVT();
19600 Alignment = ST->getAlign();
19606 bool isLegal =
false;
19608 isLegal = Subtarget->hasMVEIntegerOps() &&
19610 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19611 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19613 if (Subtarget->isThumb2())
19638 bool isSEXTLoad =
false, isNonExt;
19639 bool IsMasked =
false;
19641 VT = LD->getMemoryVT();
19642 Ptr = LD->getBasePtr();
19643 Alignment = LD->getAlign();
19647 VT = ST->getMemoryVT();
19648 Ptr = ST->getBasePtr();
19649 Alignment = ST->getAlign();
19650 isNonExt = !ST->isTruncatingStore();
19652 VT = LD->getMemoryVT();
19653 Ptr = LD->getBasePtr();
19654 Alignment = LD->getAlign();
19659 VT = ST->getMemoryVT();
19660 Ptr = ST->getBasePtr();
19661 Alignment = ST->getAlign();
19662 isNonExt = !ST->isTruncatingStore();
19667 if (Subtarget->isThumb1Only()) {
19670 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19671 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19674 if (!RHS || RHS->getZExtValue() != 4)
19676 if (Alignment <
Align(4))
19680 Base =
Op->getOperand(0);
19686 bool isLegal =
false;
19688 isLegal = Subtarget->hasMVEIntegerOps() &&
19693 if (Subtarget->isThumb2())
19707 !Subtarget->isThumb2())
19721 const APInt &DemandedElts,
19723 unsigned Depth)
const {
19726 switch (
Op.getOpcode()) {
19733 if (
Op.getResNo() == 0) {
19744 case ARMISD::CMOV: {
19759 case Intrinsic::arm_ldaex:
19760 case Intrinsic::arm_ldrex: {
19768 case ARMISD::BFI: {
19775 const APInt &Mask =
Op.getConstantOperandAPInt(2);
19776 Known.
Zero &= Mask;
19780 case ARMISD::VGETLANEs:
19781 case ARMISD::VGETLANEu: {
19782 const SDValue &SrcSV =
Op.getOperand(0);
19788 "VGETLANE index out of bounds");
19793 EVT VT =
Op.getValueType();
19799 if (
Op.getOpcode() == ARMISD::VGETLANEs)
19800 Known = Known.
sext(DstSz);
19802 Known = Known.
zext(DstSz);
19807 case ARMISD::VMOVrh: {
19810 Known = KnownOp.
zext(32);
19813 case ARMISD::CSINC:
19814 case ARMISD::CSINV:
19815 case ARMISD::CSNEG: {
19823 if (
Op.getOpcode() == ARMISD::CSINC)
19826 else if (
Op.getOpcode() == ARMISD::CSINV)
19828 else if (
Op.getOpcode() == ARMISD::CSNEG)
19835 case ARMISD::VORRIMM:
19836 case ARMISD::VBICIMM: {
19837 unsigned Encoded =
Op.getConstantOperandVal(1);
19838 unsigned DecEltBits = 0;
19841 unsigned EltBits =
Op.getScalarValueSizeInBits();
19842 if (EltBits != DecEltBits) {
19851 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
19852 APInt Imm(DecEltBits, DecodedVal);
19854 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
19855 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
19873 EVT VT =
Op.getValueType();
19879 assert(VT == MVT::i32 &&
"Unexpected integer type");
19886 unsigned Mask =
C->getZExtValue();
19889 unsigned ShrunkMask = Mask & Demanded;
19890 unsigned ExpandedMask = Mask | ~Demanded;
19894 if (ShrunkMask == 0)
19900 if (ExpandedMask == ~0U)
19903 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
19904 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
19906 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
19907 if (NewMask == Mask)
19916 if (IsLegalMask(0xFF))
19917 return UseMask(0xFF);
19920 if (IsLegalMask(0xFFFF))
19921 return UseMask(0xFFFF);
19925 if (ShrunkMask < 256)
19926 return UseMask(ShrunkMask);
19930 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
19931 return UseMask(ExpandedMask);
19946 unsigned Depth)
const {
19947 unsigned Opc =
Op.getOpcode();
19951 case ARMISD::LSRL: {
19955 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
19957 unsigned ShAmt =
Op->getConstantOperandVal(2);
19967 case ARMISD::VBICIMM: {
19969 unsigned ModImm =
Op.getConstantOperandVal(1);
19970 unsigned EltBits = 0;
19972 if ((OriginalDemandedBits & Mask) == 0)
19978 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
19993 if (!Subtarget->hasVFP2Base())
19997 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20009 unsigned S = Constraint.
size();
20011 switch (Constraint[0]) {
20023 }
else if (S == 2) {
20024 switch (Constraint[0]) {
20041 Value *CallOperandVal =
info.CallOperandVal;
20044 if (!CallOperandVal)
20048 switch (*constraint) {
20054 if (Subtarget->isThumb())
20069 if (PR == 0 || VT == MVT::Other)
20071 if (ARM::SPRRegClass.
contains(PR))
20072 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20073 if (ARM::DPRRegClass.
contains(PR))
20078using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20082 switch (Constraint.
size()) {
20085 switch (Constraint[0]) {
20087 if (Subtarget->isThumb())
20088 return RCPair(0U, &ARM::tGPRRegClass);
20089 return RCPair(0U, &ARM::GPRRegClass);
20091 if (Subtarget->isThumb())
20092 return RCPair(0U, &ARM::hGPRRegClass);
20095 if (Subtarget->isThumb1Only())
20096 return RCPair(0U, &ARM::tGPRRegClass);
20097 return RCPair(0U, &ARM::GPRRegClass);
20099 if (VT == MVT::Other)
20101 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20102 return RCPair(0U, &ARM::SPRRegClass);
20104 return RCPair(0U, &ARM::DPRRegClass);
20106 return RCPair(0U, &ARM::QPRRegClass);
20109 if (VT == MVT::Other)
20111 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20112 return RCPair(0U, &ARM::SPR_8RegClass);
20114 return RCPair(0U, &ARM::DPR_8RegClass);
20116 return RCPair(0U, &ARM::QPR_8RegClass);
20119 if (VT == MVT::Other)
20121 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20122 return RCPair(0U, &ARM::SPRRegClass);
20124 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20126 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20132 if (Constraint[0] ==
'T') {
20133 switch (Constraint[1]) {
20137 return RCPair(0U, &ARM::tGPREvenRegClass);
20139 return RCPair(0U, &ARM::tGPROddRegClass);
20148 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20149 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20153 return {0,
nullptr};
20161 std::vector<SDValue> &
Ops,
20166 if (Constraint.
size() != 1)
20169 char ConstraintLetter = Constraint[0];
20170 switch (ConstraintLetter) {
20173 case 'I':
case 'J':
case 'K':
case 'L':
20174 case 'M':
case 'N':
case 'O':
20179 int64_t CVal64 =
C->getSExtValue();
20180 int CVal = (int) CVal64;
20183 if (CVal != CVal64)
20186 switch (ConstraintLetter) {
20190 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20191 if (CVal >= 0 && CVal <= 65535)
20195 if (Subtarget->isThumb1Only()) {
20198 if (CVal >= 0 && CVal <= 255)
20200 }
else if (Subtarget->isThumb2()) {
20214 if (Subtarget->isThumb1Only()) {
20219 if (CVal >= -255 && CVal <= -1)
20225 if (CVal >= -4095 && CVal <= 4095)
20231 if (Subtarget->isThumb1Only()) {
20238 }
else if (Subtarget->isThumb2()) {
20258 if (Subtarget->isThumb1Only()) {
20261 if (CVal >= -7 && CVal < 7)
20263 }
else if (Subtarget->isThumb2()) {
20283 if (Subtarget->isThumb1Only()) {
20286 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20292 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20298 if (Subtarget->isThumb1Only()) {
20300 if (CVal >= 0 && CVal <= 31)
20306 if (Subtarget->isThumb1Only()) {
20309 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20318 if (Result.getNode()) {
20319 Ops.push_back(Result);
20329 "Unhandled Opcode in getDivRemLibcall");
20335 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20336 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20337 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20338 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20347 "Unhandled Opcode in getDivRemArgList");
20351 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20352 EVT ArgVT =
N->getOperand(i).getValueType();
20357 Args.push_back(Entry);
20365 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20366 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20367 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20368 "Register-based DivRem lowering only");
20369 unsigned Opcode =
Op->getOpcode();
20371 "Invalid opcode for Div/Rem lowering");
20373 EVT VT =
Op->getValueType(0);
20395 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20396 : Subtarget->hasDivideInARMMode();
20397 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20398 Op->getSimpleValueType(0) == MVT::i32) {
20400 const SDValue Dividend =
Op->getOperand(0);
20401 const SDValue Divisor =
Op->getOperand(1);
20402 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20406 SDValue Values[2] = {Div, Rem};
20423 if (Subtarget->isTargetWindows())
20426 TargetLowering::CallLoweringInfo CLI(DAG);
20431 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20432 return CallInfo.first;
20438 EVT VT =
N->getValueType(0);
20444 Result[0], Result[1]);
20448 std::vector<Type*> RetTyParams;
20449 Type *RetTyElement;
20459 RetTyParams.push_back(RetTyElement);
20460 RetTyParams.push_back(RetTyElement);
20473 if (Subtarget->isTargetWindows())
20481 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20484 SDNode *ResNode = CallResult.first.getNode();
20491 assert(Subtarget->isTargetWindows() &&
"unsupported target platform");
20499 "no-stack-arg-probe")) {
20503 Chain =
SP.getValue(1);
20520 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20521 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
20531 bool IsStrict =
Op->isStrictFPOpcode();
20532 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20533 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20535 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20536 "Unexpected type for custom-lowering FP_EXTEND");
20538 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20539 "With both FP DP and 16, any FP conversion is legal!");
20541 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20542 "With FP16, 16 to 32 conversion is legal!");
20545 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20550 Loc,
Op.getValueType(), SrcVal);
20565 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20566 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20567 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20568 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20572 {DstVT, MVT::Other}, {Chain, SrcVal});
20575 SrcVal = DAG.
getNode(ISD::FP_EXTEND, Loc, DstVT, SrcVal);
20579 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20580 "Unexpected type for custom-lowering FP_EXTEND");
20581 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20586 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20590 bool IsStrict =
Op->isStrictFPOpcode();
20592 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20594 EVT DstVT =
Op.getValueType();
20595 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20598 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20599 "Unexpected type for custom-lowering FP_ROUND");
20601 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20602 "With both FP DP and 16, any FP conversion is legal!");
20607 if (SrcSz == 32 && Subtarget->hasFP16())
20612 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20613 "Unexpected type for custom-lowering FP_ROUND");
20617 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20629 if (v == 0xffffffff)
20641 bool ForCodeSize)
const {
20642 if (!Subtarget->hasVFP3Base())
20644 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20646 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20649 if (VT == MVT::f32)
20651 if (VT == MVT::f64 && Subtarget->hasFP64())
20664 case Intrinsic::arm_neon_vld1:
20665 case Intrinsic::arm_neon_vld2:
20666 case Intrinsic::arm_neon_vld3:
20667 case Intrinsic::arm_neon_vld4:
20668 case Intrinsic::arm_neon_vld2lane:
20669 case Intrinsic::arm_neon_vld3lane:
20670 case Intrinsic::arm_neon_vld4lane:
20671 case Intrinsic::arm_neon_vld2dup:
20672 case Intrinsic::arm_neon_vld3dup:
20673 case Intrinsic::arm_neon_vld4dup: {
20676 auto &
DL =
I.getDataLayout();
20677 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20679 Info.ptrVal =
I.getArgOperand(0);
20681 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20687 case Intrinsic::arm_neon_vld1x2:
20688 case Intrinsic::arm_neon_vld1x3:
20689 case Intrinsic::arm_neon_vld1x4: {
20692 auto &
DL =
I.getDataLayout();
20693 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20695 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20697 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20702 case Intrinsic::arm_neon_vst1:
20703 case Intrinsic::arm_neon_vst2:
20704 case Intrinsic::arm_neon_vst3:
20705 case Intrinsic::arm_neon_vst4:
20706 case Intrinsic::arm_neon_vst2lane:
20707 case Intrinsic::arm_neon_vst3lane:
20708 case Intrinsic::arm_neon_vst4lane: {
20711 auto &
DL =
I.getDataLayout();
20712 unsigned NumElts = 0;
20713 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20714 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20717 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20720 Info.ptrVal =
I.getArgOperand(0);
20722 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20728 case Intrinsic::arm_neon_vst1x2:
20729 case Intrinsic::arm_neon_vst1x3:
20730 case Intrinsic::arm_neon_vst1x4: {
20733 auto &
DL =
I.getDataLayout();
20734 unsigned NumElts = 0;
20735 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20736 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20739 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20742 Info.ptrVal =
I.getArgOperand(0);
20744 Info.align =
I.getParamAlign(0).valueOrOne();
20749 case Intrinsic::arm_mve_vld2q:
20750 case Intrinsic::arm_mve_vld4q: {
20754 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
20756 Info.ptrVal =
I.getArgOperand(0);
20763 case Intrinsic::arm_mve_vst2q:
20764 case Intrinsic::arm_mve_vst4q: {
20767 Type *VecTy =
I.getArgOperand(1)->getType();
20768 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
20770 Info.ptrVal =
I.getArgOperand(0);
20777 case Intrinsic::arm_mve_vldr_gather_base:
20778 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
20780 Info.ptrVal =
nullptr;
20782 Info.align =
Align(1);
20786 case Intrinsic::arm_mve_vldr_gather_base_wb:
20787 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
20789 Info.ptrVal =
nullptr;
20790 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
20791 Info.align =
Align(1);
20795 case Intrinsic::arm_mve_vldr_gather_offset:
20796 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
20798 Info.ptrVal =
nullptr;
20803 Info.align =
Align(1);
20807 case Intrinsic::arm_mve_vstr_scatter_base:
20808 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
20810 Info.ptrVal =
nullptr;
20811 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
20812 Info.align =
Align(1);
20816 case Intrinsic::arm_mve_vstr_scatter_base_wb:
20817 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
20819 Info.ptrVal =
nullptr;
20820 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
20821 Info.align =
Align(1);
20825 case Intrinsic::arm_mve_vstr_scatter_offset:
20826 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
20828 Info.ptrVal =
nullptr;
20833 Info.align =
Align(1);
20837 case Intrinsic::arm_ldaex:
20838 case Intrinsic::arm_ldrex: {
20839 auto &
DL =
I.getDataLayout();
20840 Type *ValTy =
I.getParamElementType(0);
20843 Info.ptrVal =
I.getArgOperand(0);
20845 Info.align =
DL.getABITypeAlign(ValTy);
20849 case Intrinsic::arm_stlex:
20850 case Intrinsic::arm_strex: {
20851 auto &
DL =
I.getDataLayout();
20852 Type *ValTy =
I.getParamElementType(1);
20855 Info.ptrVal =
I.getArgOperand(1);
20857 Info.align =
DL.getABITypeAlign(ValTy);
20861 case Intrinsic::arm_stlexd:
20862 case Intrinsic::arm_strexd:
20864 Info.memVT = MVT::i64;
20865 Info.ptrVal =
I.getArgOperand(2);
20867 Info.align =
Align(8);
20871 case Intrinsic::arm_ldaexd:
20872 case Intrinsic::arm_ldrexd:
20874 Info.memVT = MVT::i64;
20875 Info.ptrVal =
I.getArgOperand(0);
20877 Info.align =
Align(8);
20892 assert(Ty->isIntegerTy());
20894 unsigned Bits = Ty->getPrimitiveSizeInBits();
20895 if (Bits == 0 || Bits > 32)
20901 unsigned Index)
const {
20911 if (!Subtarget->hasDataBarrier()) {
20915 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
20916 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
20917 Builder.getInt32(0), Builder.getInt32(7),
20918 Builder.getInt32(10), Builder.getInt32(5)};
20919 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
20929 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
20950 if (Subtarget->preferISHSTBarriers())
20983 bool has64BitAtomicStore;
20984 if (Subtarget->isMClass())
20985 has64BitAtomicStore =
false;
20986 else if (Subtarget->isThumb())
20987 has64BitAtomicStore = Subtarget->hasV7Ops();
20989 has64BitAtomicStore = Subtarget->hasV6Ops();
20991 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21005 bool has64BitAtomicLoad;
21006 if (Subtarget->isMClass())
21007 has64BitAtomicLoad =
false;
21008 else if (Subtarget->isThumb())
21009 has64BitAtomicLoad = Subtarget->hasV7Ops();
21011 has64BitAtomicLoad = Subtarget->hasV6Ops();
21027 if (Subtarget->isMClass())
21028 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21029 else if (Subtarget->isThumb())
21030 hasAtomicRMW = Subtarget->hasV7Ops();
21032 hasAtomicRMW = Subtarget->hasV6Ops();
21033 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21056 bool HasAtomicCmpXchg;
21057 if (Subtarget->isMClass())
21058 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21059 else if (Subtarget->isThumb())
21060 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21062 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21064 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21071 return InsertFencesForAtomic;
21076 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21081 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21084 RTLIB::LibcallImpl SecurityCookieVar =
21086 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21087 SecurityCookieVar != RTLIB::Unsupported) {
21098 F->addParamAttr(0, Attribute::AttrKind::InReg);
21105 unsigned &
Cost)
const {
21107 if (!Subtarget->hasNEON())
21136 unsigned Opcode =
Op.getOpcode();
21138 case ARMISD::VORRIMM:
21139 case ARMISD::VBICIMM:
21147 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21151 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21156 if (!Subtarget->hasV7Ops())
21162 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21164 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21172 if (Subtarget->hasMinSize() && !Subtarget->isTargetWindows())
21181 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21187 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21189 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21192 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21194 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21195 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21196 if (!Subtarget->isLittle())
21198 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21199 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21200 return Builder.CreateOr(
21201 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21205 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21206 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21209 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21210 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21215 if (!Subtarget->hasV7Ops())
21217 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21223 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21231 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21235 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21236 if (!Subtarget->isLittle())
21238 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21241 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21245 CallInst *CI = Builder.CreateCall(
21246 Strex, {Builder.CreateZExtOrBitCast(
21256 return Subtarget->isMClass();
21264 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21271 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21274 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21282 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21290 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21293 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21298 if (Subtarget->hasNEON() && VecSize == 64)
21300 return VecSize % 128 == 0;
21304 if (Subtarget->hasNEON())
21306 if (Subtarget->hasMVEIntegerOps())
21326 "Invalid interleave factor");
21327 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21329 "Unmatched number of shufflevectors and indices");
21334 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21337 Type *EltTy = VecTy->getElementType();
21340 Align Alignment = LI->getAlign();
21358 Value *BaseAddr = LI->getPointerOperand();
21360 if (NumLoads > 1) {
21364 VecTy->getNumElements() / NumLoads);
21370 if (Subtarget->hasNEON()) {
21371 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21372 Type *Tys[] = {VecTy, PtrTy};
21373 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21374 Intrinsic::arm_neon_vld3,
21375 Intrinsic::arm_neon_vld4};
21378 Ops.push_back(BaseAddr);
21379 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21381 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21384 assert((Factor == 2 || Factor == 4) &&
21385 "expected interleave factor of 2 or 4 for MVE");
21387 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21388 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21389 Type *Tys[] = {VecTy, PtrTy};
21392 Ops.push_back(BaseAddr);
21393 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21403 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21407 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21408 VecTy->getNumElements() * Factor);
21414 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21416 unsigned Index = Indices[i];
21418 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21422 SubVec = Builder.CreateIntToPtr(
21426 SubVecs[SV].push_back(SubVec);
21435 auto &SubVec = SubVecs[SVI];
21438 SVI->replaceAllUsesWith(WideVec);
21474 const APInt &GapMask)
const {
21476 "Invalid interleave factor");
21481 "Unexpected mask on store");
21484 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21486 unsigned LaneLen = VecTy->getNumElements() / Factor;
21487 Type *EltTy = VecTy->getElementType();
21491 Align Alignment =
SI->getAlign();
21508 Type *IntTy =
DL.getIntPtrType(EltTy);
21513 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21514 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21520 Value *BaseAddr =
SI->getPointerOperand();
21522 if (NumStores > 1) {
21525 LaneLen /= NumStores;
21535 if (Subtarget->hasNEON()) {
21536 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21537 Intrinsic::arm_neon_vst3,
21538 Intrinsic::arm_neon_vst4};
21539 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21540 Type *Tys[] = {PtrTy, SubVecTy};
21543 Ops.push_back(BaseAddr);
21545 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21546 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21548 assert((Factor == 2 || Factor == 4) &&
21549 "expected interleave factor of 2 or 4 for MVE");
21551 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21552 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21553 Type *Tys[] = {PtrTy, SubVecTy};
21556 Ops.push_back(BaseAddr);
21558 for (
unsigned F = 0;
F < Factor;
F++) {
21559 Ops.push_back(Builder.getInt32(
F));
21560 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21566 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21569 if (StoreCount > 0)
21570 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21571 BaseAddr, LaneLen * Factor);
21576 for (
unsigned i = 0; i < Factor; i++) {
21577 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21578 if (Mask[IdxI] >= 0) {
21579 Shuffles.
push_back(Builder.CreateShuffleVector(
21582 unsigned StartMask = 0;
21583 for (
unsigned j = 1; j < LaneLen; j++) {
21584 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21585 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21586 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21596 Shuffles.
push_back(Builder.CreateShuffleVector(
21617 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21621 Members += SubMembers;
21627 Members += SubMembers * AT->getNumElements();
21628 }
else if (Ty->isFloatTy()) {
21633 }
else if (Ty->isDoubleTy()) {
21645 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21647 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21649 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21662 return (Members > 0 && Members <= 4);
21668 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21670 return ABITypeAlign;
21675 assert(StackAlign &&
"data layout string is missing stack alignment");
21676 return std::min(ABITypeAlign, *StackAlign);
21685 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21694 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
21695 return IsHA || IsIntArray;
21699 const Constant *PersonalityFn)
const {
21707 const Constant *PersonalityFn)
const {
21720void ARMTargetLowering::insertCopiesSplitCSR(
21724 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21734 RC = &ARM::GPRRegClass;
21735 else if (ARM::DPRRegClass.
contains(*
I))
21736 RC = &ARM::DPRRegClass;
21746 assert(Entry->getParent()->getFunction().hasFnAttribute(
21747 Attribute::NoUnwind) &&
21748 "Function should be nounwind in insertCopiesSplitCSR!");
21749 Entry->addLiveIn(*
I);
21754 for (
auto *Exit : Exits)
21756 TII->get(TargetOpcode::COPY), *
I)
21767 return Subtarget->hasMVEIntegerOps();
21777 unsigned NumElements = VTy->getNumElements();
21784 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
21785 return Subtarget->hasMVEFloatOps();
21790 return Subtarget->hasMVEIntegerOps() &&
21791 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
21792 ScalarTy->isIntegerTy(32));
21796 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
21807 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
21809 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
21811 if (TyWidth > 128) {
21812 int Stride = Ty->getNumElements() / 2;
21816 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
21818 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
21819 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
21820 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
21821 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
21822 Value *LowerSplitAcc =
nullptr;
21823 Value *UpperSplitAcc =
nullptr;
21826 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
21827 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
21831 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
21833 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
21835 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
21836 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
21843 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
21846 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
21848 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
21849 {ConstRotation, InputB, InputA});
21854 auto *ConstHalving = ConstantInt::get(IntTy, 1);
21857 ConstRotation = ConstantInt::get(IntTy, 0);
21859 ConstRotation = ConstantInt::get(IntTy, 1);
21861 if (!ConstRotation)
21864 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
21865 {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...
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)