84#include "llvm/IR/IntrinsicsARM.h"
119#define DEBUG_TYPE "arm-isel"
122STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
123STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
125 "Number of constants with their storage promoted into constant pools");
129 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
134 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
139 cl::desc(
"Maximum size of constant to promote into a constant pool"),
143 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
148 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
153 cl::desc(
"Maximum number of base-updates to check generating postindex."),
161 ARM::R0, ARM::R1, ARM::R2, ARM::R3
175void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
176 if (VT != PromotedLdStVT) {
185 if (ElemTy != MVT::f64)
189 if (ElemTy == MVT::i32) {
233void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
235 addTypeForNEON(VT, MVT::f64);
238void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
240 addTypeForNEON(VT, MVT::v2f64);
243void ARMTargetLowering::setAllExpand(
MVT VT) {
256void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
263void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
264 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
266 for (
auto VT : IntTypes) {
340 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
341 for (
auto VT : FloatTypes) {
415 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
416 for (
auto VT : LongTypes) {
433 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
434 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
435 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
452 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
461 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
462 for (
auto VT : pTypes) {
513 RegInfo(Subtarget->getRegisterInfo()),
514 Itins(Subtarget->getInstrItineraryData()) {
520 const Triple &TT = TM.getTargetTriple();
522 if (TT.isOSBinFormatMachO()) {
524 if (Subtarget->isThumb() && Subtarget->hasVFP2Base() &&
525 Subtarget->hasARMOps() && !Subtarget->useSoftFloat()) {
527 static const struct {
528 const RTLIB::Libcall
Op;
529 const RTLIB::LibcallImpl Impl;
532 { RTLIB::ADD_F32, RTLIB::impl___addsf3vfp },
533 { RTLIB::SUB_F32, RTLIB::impl___subsf3vfp },
534 { RTLIB::MUL_F32, RTLIB::impl___mulsf3vfp },
535 { RTLIB::DIV_F32, RTLIB::impl___divsf3vfp },
538 { RTLIB::ADD_F64, RTLIB::impl___adddf3vfp },
539 { RTLIB::SUB_F64, RTLIB::impl___subdf3vfp },
540 { RTLIB::MUL_F64, RTLIB::impl___muldf3vfp },
541 { RTLIB::DIV_F64, RTLIB::impl___divdf3vfp },
544 { RTLIB::OEQ_F32, RTLIB::impl___eqsf2vfp },
545 { RTLIB::UNE_F32, RTLIB::impl___nesf2vfp },
546 { RTLIB::OLT_F32, RTLIB::impl___ltsf2vfp },
547 { RTLIB::OLE_F32, RTLIB::impl___lesf2vfp },
548 { RTLIB::OGE_F32, RTLIB::impl___gesf2vfp },
549 { RTLIB::OGT_F32, RTLIB::impl___gtsf2vfp },
550 { RTLIB::UO_F32, RTLIB::impl___unordsf2vfp },
553 { RTLIB::OEQ_F64, RTLIB::impl___eqdf2vfp },
554 { RTLIB::UNE_F64, RTLIB::impl___nedf2vfp },
555 { RTLIB::OLT_F64, RTLIB::impl___ltdf2vfp },
556 { RTLIB::OLE_F64, RTLIB::impl___ledf2vfp },
557 { RTLIB::OGE_F64, RTLIB::impl___gedf2vfp },
558 { RTLIB::OGT_F64, RTLIB::impl___gtdf2vfp },
559 { RTLIB::UO_F64, RTLIB::impl___unorddf2vfp },
564 { RTLIB::FPTOSINT_F64_I32, RTLIB::impl___fixdfsivfp },
565 { RTLIB::FPTOUINT_F64_I32, RTLIB::impl___fixunsdfsivfp },
566 { RTLIB::FPTOSINT_F32_I32, RTLIB::impl___fixsfsivfp },
567 { RTLIB::FPTOUINT_F32_I32, RTLIB::impl___fixunssfsivfp },
570 { RTLIB::FPROUND_F64_F32, RTLIB::impl___truncdfsf2vfp },
571 { RTLIB::FPEXT_F32_F64, RTLIB::impl___extendsfdf2vfp },
578 { RTLIB::SINTTOFP_I32_F64, RTLIB::impl___floatsidfvfp },
579 { RTLIB::UINTTOFP_I32_F64, RTLIB::impl___floatunssidfvfp },
580 { RTLIB::SINTTOFP_I32_F32, RTLIB::impl___floatsisfvfp },
581 { RTLIB::UINTTOFP_I32_F32, RTLIB::impl___floatunssisfvfp },
585 for (
const auto &LC : LibraryCalls)
590 if (Subtarget->isThumb1Only())
595 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
596 Subtarget->hasFPRegs()) {
605 if (!Subtarget->hasVFP2Base())
606 setAllExpand(MVT::f32);
607 if (!Subtarget->hasFP64())
608 setAllExpand(MVT::f64);
611 if (Subtarget->hasFullFP16()) {
620 if (Subtarget->hasBF16()) {
622 setAllExpand(MVT::bf16);
623 if (!Subtarget->hasFullFP16())
635 addAllExtLoads(VT, InnerVT,
Expand);
644 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
647 if (!Subtarget->hasV8_1MMainlineOps())
656 if (Subtarget->hasMVEIntegerOps())
657 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
660 if (Subtarget->hasLOB()) {
664 if (Subtarget->hasNEON()) {
665 addDRTypeForNEON(MVT::v2f32);
666 addDRTypeForNEON(MVT::v8i8);
667 addDRTypeForNEON(MVT::v4i16);
668 addDRTypeForNEON(MVT::v2i32);
669 addDRTypeForNEON(MVT::v1i64);
671 addQRTypeForNEON(MVT::v4f32);
672 addQRTypeForNEON(MVT::v2f64);
673 addQRTypeForNEON(MVT::v16i8);
674 addQRTypeForNEON(MVT::v8i16);
675 addQRTypeForNEON(MVT::v4i32);
676 addQRTypeForNEON(MVT::v2i64);
678 if (Subtarget->hasFullFP16()) {
679 addQRTypeForNEON(MVT::v8f16);
680 addDRTypeForNEON(MVT::v4f16);
683 if (Subtarget->hasBF16()) {
684 addQRTypeForNEON(MVT::v8bf16);
685 addDRTypeForNEON(MVT::v4bf16);
689 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
729 if (Subtarget->hasNEON()) {
770 ISD::FRINT, ISD::FTRUNC, ISD::FROUNDEVEN}) {
842 if (!Subtarget->hasVFP4Base()) {
851 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
860 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
869 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
877 if (Subtarget->hasMVEIntegerOps()) {
882 if (Subtarget->hasMVEFloatOps()) {
886 if (!Subtarget->hasFP64()) {
931 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
934 if (Subtarget->hasFullFP16()) {
940 if (!Subtarget->hasFP16()) {
966 if (!Subtarget->isThumb1Only()) {
991 if (Subtarget->hasDSP()) {
1001 if (Subtarget->hasBaseDSP()) {
1009 if (Subtarget->isThumb1Only()) {
1013 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
1014 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1029 if (Subtarget->hasMVEIntegerOps())
1033 if (Subtarget->isThumb1Only()) {
1039 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1053 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1062 if (Subtarget->hasPerfMon())
1066 if (!Subtarget->hasV6Ops())
1069 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1070 : Subtarget->hasDivideInARMMode();
1077 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1089 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1090 TT.isTargetMuslAEABI() || TT.isOSWindows()) {
1093 HasStandaloneRem =
false;
1120 if (TT.isOSWindows())
1127 InsertFencesForAtomic =
false;
1128 if (Subtarget->hasAnyDataBarrier() &&
1129 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1133 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1138 if (!Subtarget->hasAcquireRelease() ||
1141 InsertFencesForAtomic =
true;
1147 if (Subtarget->hasDataBarrier())
1148 InsertFencesForAtomic =
true;
1168 if (!InsertFencesForAtomic) {
1175 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1187 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1188 Subtarget->hasForced32BitAtomics()) {
1202 if (!Subtarget->hasV6Ops()) {
1208 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1209 !Subtarget->isThumb1Only()) {
1238 if (Subtarget->hasFullFP16()) {
1248 if (Subtarget->hasFullFP16())
1263 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1264 !Subtarget->isThumb1Only()) {
1271 if (!Subtarget->hasVFP4Base()) {
1277 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1279 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1285 if (!Subtarget->hasFP16()) {
1307 if (Subtarget->hasFPARMv8Base()) {
1317 if (Subtarget->hasNEON()) {
1324 if (Subtarget->hasFP64()) {
1338 if (Subtarget->hasFullFP16()) {
1363 if (Subtarget->hasNEON()) {
1375 if (Subtarget->hasV8Ops()) {
1390 if (Subtarget->hasFullFP16()) {
1418 if (TT.isOSWindows()) {
1435 if (Subtarget->hasMVEIntegerOps())
1438 if (Subtarget->hasV6Ops())
1440 if (Subtarget->isThumb1Only())
1443 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1444 Subtarget->isThumb2()) {
1450 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1451 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1473 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1479 return Subtarget->useSoftFloat();
1483 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1496std::pair<const TargetRegisterClass *, uint8_t>
1507 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1508 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1509 RRC = &ARM::DPRRegClass;
1514 if (Subtarget->useNEONForSinglePrecisionFP())
1517 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1518 case MVT::v4f32:
case MVT::v2f64:
1519 RRC = &ARM::DPRRegClass;
1523 RRC = &ARM::DPRRegClass;
1527 RRC = &ARM::DPRRegClass;
1531 return std::make_pair(RRC,
Cost);
1535#define MAKE_CASE(V) \
1754 if ((Subtarget->hasMVEIntegerOps() &&
1755 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1756 VT == MVT::v16i8)) ||
1757 (Subtarget->hasMVEFloatOps() &&
1758 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1772 if (Subtarget->hasNEON()) {
1773 if (VT == MVT::v4i64)
1774 return &ARM::QQPRRegClass;
1775 if (VT == MVT::v8i64)
1776 return &ARM::QQQQPRRegClass;
1778 if (Subtarget->hasMVEIntegerOps()) {
1779 if (VT == MVT::v4i64)
1780 return &ARM::MQQPRRegClass;
1781 if (VT == MVT::v8i64)
1782 return &ARM::MQQQQPRRegClass;
1791 Align &PrefAlign)
const {
1798 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1810 unsigned NumVals =
N->getNumValues();
1814 for (
unsigned i = 0; i != NumVals; ++i) {
1815 EVT VT =
N->getValueType(i);
1816 if (VT == MVT::Glue || VT == MVT::Other)
1822 if (!
N->isMachineOpcode())
1830 if (
MCID.getNumDefs() == 0)
1832 if (!Itins->isEmpty() &&
1833 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1847 return Const->getZExtValue() == 16;
1855 return Const->getZExtValue() == 16;
1863 return Const->getZExtValue() == 16;
1932 bool isVarArg)
const {
1951 if (!
getTM().isAAPCS_ABI())
1953 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1961 if (!
getTM().isAAPCS_ABI()) {
1962 if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() && !isVarArg)
1965 }
else if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() &&
1974 bool isVarArg)
const {
1975 return CCAssignFnForNode(CC,
false, isVarArg);
1979 bool isVarArg)
const {
1980 return CCAssignFnForNode(CC,
true, isVarArg);
1987 bool isVarArg)
const {
1988 switch (getEffectiveCallingConv(CC, isVarArg)) {
2014 if (Subtarget->hasFullFP16()) {
2019 Val = DAG.
getNode(ISD::BITCAST, dl, ValVT, Val);
2027 if (Subtarget->hasFullFP16()) {
2031 Val = DAG.
getNode(ISD::BITCAST, dl,
2036 return DAG.
getNode(ISD::BITCAST, dl, LocVT, Val);
2041SDValue ARMTargetLowering::LowerCallResult(
2045 SDValue ThisVal,
bool isCmseNSCall)
const {
2053 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
2054 CCValAssign VA = RVLocs[i];
2058 if (i == 0 && isThisReturn) {
2060 "unexpected return calling convention register assignment");
2078 if (!Subtarget->isLittle())
2095 if (!Subtarget->isLittle())
2138std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
2140 bool IsTailCall,
int SPDiff)
const {
2142 MachinePointerInfo DstInfo;
2162 return std::make_pair(DstAddr, DstInfo);
2171ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
2184 if (!SrcFrameIdxNode || !DstFrameIdxNode)
2187 int SrcFI = SrcFrameIdxNode->getIndex();
2188 int DstFI = DstFrameIdxNode->getIndex();
2190 "byval passed in non-fixed stack slot");
2212 if (SrcOffset == DstOffset)
2220 RegsToPassVector &RegsToPass,
2227 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
2228 unsigned id = Subtarget->isLittle() ? 0 : 1;
2240 MachinePointerInfo DstInfo;
2241 std::tie(DstAddr, DstInfo) =
2242 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2259 SelectionDAG &DAG = CLI.
DAG;
2261 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2262 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2263 SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2270 const CallBase *CB = CLI.
CB;
2273 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2275 MachineFunction::CallSiteInfo CSInfo;
2276 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2277 bool isThisReturn =
false;
2278 bool isCmseNSCall =
false;
2279 bool isSibCall =
false;
2280 bool PreferIndirect =
false;
2281 bool GuardWithBTI =
false;
2291 !Subtarget->noBTIAtReturnTwice())
2296 CSInfo = MachineFunction::CallSiteInfo(*CB);
2300 isCmseNSCall =
true;
2303 if (!Subtarget->supportsTailCall())
2319 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2320 count_if(GV->users(), [&BB](
const User *U) {
2321 return isa<Instruction>(U) &&
2322 cast<Instruction>(U)->getParent() == BB;
2329 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2343 "site marked musttail");
2346 unsigned NumBytes = CCInfo.getStackSize();
2355 if (isTailCall && !isSibCall) {
2356 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2357 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2362 assert(StackAlign &&
"data layout string is missing stack alignment");
2363 NumBytes =
alignTo(NumBytes, *StackAlign);
2368 SPDiff = NumReusableBytes - NumBytes;
2372 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2388 RegsToPassVector RegsToPass;
2397 DenseMap<unsigned, SDValue> ByValTemporaries;
2401 for (
const CCValAssign &VA : ArgLocs) {
2403 SDValue Src = OutVals[ArgIdx];
2404 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2406 if (!
Flags.isByVal())
2410 MachinePointerInfo DstInfo;
2411 std::tie(Dst, DstInfo) =
2412 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2413 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2415 if (Copy == NoCopy) {
2420 }
else if (Copy == CopyOnce) {
2424 ByValTemporaries[ArgIdx] = Src;
2426 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2430 int TempFrameIdx = MFI.CreateStackObject(
2431 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2439 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2440 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2443 ByValTemporaries[ArgIdx] = Temp;
2446 if (!ByValCopyChains.
empty())
2456 bool AfterFormalArgLoads =
false;
2460 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2462 ++i, ++realArgIdx) {
2463 CCValAssign &VA = ArgLocs[i];
2464 SDValue Arg = OutVals[realArgIdx];
2465 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2466 bool isByVal =
Flags.isByVal();
2486 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2491 AfterFormalArgLoads =
true;
2503 auto ArgVT = Outs[realArgIdx].ArgVT;
2504 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2522 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2523 StackPtr, MemOpChains, isTailCall, SPDiff);
2527 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2528 StackPtr, MemOpChains, isTailCall, SPDiff);
2532 MachinePointerInfo DstInfo;
2533 std::tie(DstAddr, DstInfo) =
2534 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2538 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2539 StackPtr, MemOpChains, isTailCall, SPDiff);
2541 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2542 Outs[0].VT == MVT::i32) {
2544 "unexpected calling convention register assignment");
2545 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2546 "unexpected use of 'returned'");
2547 isThisReturn =
true;
2552 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2553 }
else if (isByVal) {
2555 unsigned offset = 0;
2559 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2560 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2563 bool NeedsStackCopy;
2564 if (
auto It = ByValTemporaries.
find(realArgIdx);
2565 It != ByValTemporaries.
end()) {
2566 ByValSrc = It->second;
2567 NeedsStackCopy =
true;
2570 NeedsStackCopy = !isTailCall;
2574 if (CurByValIdx < ByValArgsCount) {
2575 unsigned RegBegin, RegEnd;
2576 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2580 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2584 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2587 RegsToPass.push_back(std::make_pair(j, Load));
2592 offset = RegEnd - RegBegin;
2594 CCInfo.nextInRegsParam();
2599 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2602 MachinePointerInfo DstInfo;
2603 std::tie(Dst, DstInfo) =
2604 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2612 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2613 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2620 MachinePointerInfo DstInfo;
2621 std::tie(DstAddr, DstInfo) =
2622 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2629 if (!MemOpChains.
empty())
2635 for (
const auto &[
Reg,
N] : RegsToPass) {
2643 bool isDirect =
false;
2646 const GlobalValue *GVal =
nullptr;
2648 GVal =
G->getGlobal();
2649 bool isStub = !TM.shouldAssumeDSOLocal(GVal) && Subtarget->isTargetMachO();
2651 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2652 bool isLocalARMFunc =
false;
2655 if (Subtarget->genLongCalls()) {
2657 "long-calls codegen is not position independent!");
2662 if (Subtarget->genExecuteOnly()) {
2663 if (Subtarget->useMovt())
2681 const char *Sym = S->getSymbol();
2683 if (Subtarget->genExecuteOnly()) {
2684 if (Subtarget->useMovt())
2703 if (!PreferIndirect) {
2708 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2710 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2711 assert(Subtarget->isTargetMachO() &&
"WrapperPIC use on non-MachO?");
2720 }
else if (Subtarget->isTargetCOFF()) {
2721 assert(Subtarget->isTargetWindows() &&
2722 "Windows is the only supported COFF target");
2726 else if (!TM.shouldAssumeDSOLocal(GVal))
2742 const char *Sym = S->getSymbol();
2743 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2745 ARMConstantPoolValue *CPV =
2747 ARMPCLabelIndex, 4);
2761 assert(!isARMFunc && !isDirect &&
2762 "Cannot handle call to ARM function or direct call");
2766 "call to non-secure function would require "
2767 "passing arguments on stack",
2773 "call to non-secure function would return value through pointer",
2780 if (Subtarget->isThumb()) {
2783 else if (isCmseNSCall)
2785 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2790 if (!isDirect && !Subtarget->hasV5TOps())
2792 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2794 !Subtarget->hasMinSize())
2805 if (isTailCall && !isSibCall) {
2810 std::vector<SDValue>
Ops;
2811 Ops.push_back(Chain);
2812 Ops.push_back(Callee);
2820 for (
const auto &[
Reg,
N] : RegsToPass)
2824 const uint32_t *
Mask;
2825 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2833 isThisReturn =
false;
2839 assert(Mask &&
"Missing call preserved mask for calling convention");
2843 Ops.push_back(InGlue);
2854 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2863 uint64_t CalleePopBytes =
2866 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2872 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2873 InVals, isThisReturn,
2874 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2881void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2882 Align Alignment)
const {
2884 Alignment = std::max(Alignment,
Align(4));
2890 unsigned AlignInRegs = Alignment.
value() / 4;
2891 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2892 for (
unsigned i = 0; i < Waste; ++i)
2898 unsigned Excess = 4 * (ARM::R4 -
Reg);
2905 if (NSAAOffset != 0 &&
Size > Excess) {
2917 unsigned ByValRegBegin =
Reg;
2918 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2922 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2928 Size = std::max<int>(
Size - Excess, 0);
2936bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2942 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2943 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2944 const SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2945 const SelectionDAG &DAG = CLI.
DAG;
2950 assert(Subtarget->supportsTailCall());
2963 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2965 if (!(Subtarget->isThumb1Only() ||
2966 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2967 AddressRegisters.
insert(ARM::R12);
2968 for (
const CCValAssign &AL : ArgLocs)
2970 AddressRegisters.
erase(
AL.getLocReg());
2971 if (AddressRegisters.
empty()) {
2972 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2991 <<
" (guaranteed tail-call CC)\n");
2992 return CalleeCC == CallerCC;
2997 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2999 if (isCalleeStructRet != isCallerStructRet) {
3012 const GlobalValue *GV =
G->getGlobal();
3015 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
3016 TT.isOSBinFormatMachO())) {
3025 getEffectiveCallingConv(CalleeCC, isVarArg),
3026 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
3033 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3034 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
3035 if (CalleeCC != CallerCC) {
3036 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
3037 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
3046 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
3056 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
3075 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
3084 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
3097 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
3100 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
3104 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
3131 bool isLittleEndian = Subtarget->isLittle();
3134 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3143 "secure entry function would return value through pointer",
3148 for (
unsigned i = 0, realRVLocIdx = 0;
3150 ++i, ++realRVLocIdx) {
3151 CCValAssign &VA = RVLocs[i];
3154 SDValue Arg = OutVals[realRVLocIdx];
3155 bool ReturnF16 =
false;
3157 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
3190 auto RetVT = Outs[realRVLocIdx].ArgVT;
3212 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3216 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3222 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3234 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3236 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3241 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3251 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3277 !Subtarget->isMClass()) {
3278 if (Subtarget->isThumb1Only())
3285 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3288bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3289 if (
N->getNumValues() != 1)
3291 if (!
N->hasNUsesOfValue(1, 0))
3295 SDNode *
Copy = *
N->user_begin();
3299 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3301 TCChain =
Copy->getOperand(0);
3303 SDNode *VMov =
Copy;
3305 SmallPtrSet<SDNode*, 2>
Copies;
3306 for (SDNode *U : VMov->
users()) {
3314 for (SDNode *U : VMov->
users()) {
3315 SDValue UseChain =
U->getOperand(0);
3323 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3329 }
else if (
Copy->getOpcode() == ISD::BITCAST) {
3331 if (!
Copy->hasOneUse())
3338 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3340 TCChain =
Copy->getOperand(0);
3345 bool HasRet =
false;
3346 for (
const SDNode *U :
Copy->users()) {
3360bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3361 if (!Subtarget->supportsTailCall())
3378 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3394 EVT PtrVT =
Op.getValueType();
3404 if (Subtarget->genExecuteOnly()) {
3406 auto *
T =
CP->getType();
3407 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3409 auto GV =
new GlobalVariable(
3417 return LowerGlobalAddress(GA, DAG);
3422 Align CPAlign =
CP->getAlign();
3423 if (Subtarget->isThumb1Only())
3424 CPAlign = std::max(CPAlign,
Align(4));
3425 if (
CP->isMachineConstantPoolEntry())
3437 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3446 unsigned ARMPCLabelIndex = 0;
3452 if (!IsPositionIndependent) {
3455 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3466 if (!IsPositionIndependent)
3497ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3499 assert(Subtarget->isTargetDarwin() &&
3500 "This function expects a Darwin target");
3505 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3511 MVT::i32,
DL, Chain, DescAddr,
3526 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3535 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3541ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3543 assert(Subtarget->isTargetWindows() &&
"Windows specific TLS lowering");
3567 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3576 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3582 MachinePointerInfo());
3602 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3604 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3606 ARMConstantPoolValue *CPV =
3624 TargetLowering::CallLoweringInfo CLI(DAG);
3629 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3630 return CallResult.first;
3639 const GlobalValue *GV = GA->
getGlobal();
3649 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3652 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3653 ARMConstantPoolValue *CPV =
3660 PtrVT, dl, Chain,
Offset,
3668 PtrVT, dl, Chain,
Offset,
3673 ARMConstantPoolValue *CPV =
3678 PtrVT, dl, Chain,
Offset,
3693 if (Subtarget->isTargetDarwin())
3694 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3696 if (Subtarget->isTargetWindows())
3697 return LowerGlobalTLSAddressWindows(
Op, DAG);
3700 assert(Subtarget->isTargetELF() &&
"Only ELF implemented here");
3706 return LowerToTLSGeneralDynamicModel(GA, DAG);
3709 return LowerToTLSExecModels(GA, DAG, model);
3718 while (!Worklist.
empty()) {
3726 if (!
I ||
I->getParent()->getParent() !=
F)
3755 if (!GVar || !GVar->hasInitializer() ||
3756 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3757 !GVar->hasLocalLinkage())
3762 auto *
Init = GVar->getInitializer();
3764 Init->needsDynamicRelocation())
3776 unsigned RequiredPadding = 4 - (
Size % 4);
3777 bool PaddingPossible =
3778 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3783 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3807 if (RequiredPadding != 4) {
3812 while (RequiredPadding--)
3824 ++NumConstpoolPromoted;
3830 if (!(GV = GA->getAliaseeObject()))
3833 return V->isConstant();
3842 return LowerGlobalAddressWindows(
Op, DAG);
3844 return LowerGlobalAddressELF(
Op, DAG);
3846 return LowerGlobalAddressDarwin(
Op, DAG);
3858 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3871 }
else if (Subtarget->isROPI() && IsRO) {
3876 }
else if (Subtarget->isRWPI() && !IsRO) {
3879 if (Subtarget->useMovt()) {
3884 ARMConstantPoolValue *CPV =
3901 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3902 if (Subtarget->useMovt())
3919 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3920 "ROPI/RWPI not currently supported for Darwin");
3925 if (Subtarget->useMovt())
3936 if (Subtarget->isGVIndirectSymbol(GV))
3944 assert(Subtarget->isTargetWindows() &&
"non-Windows COFF is not supported");
3945 assert(Subtarget->useMovt() &&
3946 "Windows on ARM expects to use movw/movt");
3947 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3948 "ROPI/RWPI not currently supported for Windows");
3955 else if (!TM.shouldAssumeDSOLocal(GV))
3979 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3980 Op.getOperand(1), Val);
3997SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
4000 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
4004 case Intrinsic::arm_gnu_eabi_mcount: {
4010 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
4011 const uint32_t *
Mask =
4013 assert(Mask &&
"Missing call preserved mask for calling convention");
4018 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
4022 if (Subtarget->isThumb())
4025 ARM::tBL_PUSHLR, dl, ResultTys,
4026 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
4027 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
4031 {ReturnAddress, Callee, RegisterMask, Chain}),
4040 unsigned IntNo =
Op.getConstantOperandVal(0);
4044 case Intrinsic::thread_pointer: {
4048 case Intrinsic::arm_cls: {
4049 const SDValue &Operand =
Op.getOperand(1);
4050 const EVT VTy =
Op.getValueType();
4061 case Intrinsic::arm_cls64: {
4064 const SDValue &Operand =
Op.getOperand(1);
4065 const EVT VTy =
Op.getValueType();
4088 case Intrinsic::eh_sjlj_lsda: {
4090 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4095 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
4096 ARMConstantPoolValue *CPV =
4105 if (IsPositionIndependent) {
4111 case Intrinsic::arm_neon_vabs:
4114 case Intrinsic::arm_neon_vabds:
4115 if (
Op.getValueType().isInteger())
4117 Op.getOperand(1),
Op.getOperand(2));
4119 case Intrinsic::arm_neon_vabdu:
4121 Op.getOperand(1),
Op.getOperand(2));
4122 case Intrinsic::arm_neon_vmulls:
4123 case Intrinsic::arm_neon_vmullu: {
4124 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
4126 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4127 Op.getOperand(1),
Op.getOperand(2));
4129 case Intrinsic::arm_neon_vminnm:
4130 case Intrinsic::arm_neon_vmaxnm: {
4131 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
4132 ? ISD::FMINNUM : ISD::FMAXNUM;
4133 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4134 Op.getOperand(1),
Op.getOperand(2));
4136 case Intrinsic::arm_neon_vminu:
4137 case Intrinsic::arm_neon_vmaxu: {
4138 if (
Op.getValueType().isFloatingPoint())
4140 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
4142 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4143 Op.getOperand(1),
Op.getOperand(2));
4145 case Intrinsic::arm_neon_vmins:
4146 case Intrinsic::arm_neon_vmaxs: {
4148 if (!
Op.getValueType().isFloatingPoint()) {
4149 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4151 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4152 Op.getOperand(1),
Op.getOperand(2));
4154 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4155 ? ISD::FMINIMUM : ISD::FMAXIMUM;
4156 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4157 Op.getOperand(1),
Op.getOperand(2));
4159 case Intrinsic::arm_neon_vtbl1:
4161 Op.getOperand(1),
Op.getOperand(2));
4162 case Intrinsic::arm_neon_vtbl2:
4164 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4165 case Intrinsic::arm_mve_pred_i2v:
4166 case Intrinsic::arm_mve_pred_v2i:
4169 case Intrinsic::arm_mve_vreinterpretq:
4172 case Intrinsic::arm_mve_lsll:
4174 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4175 case Intrinsic::arm_mve_asrl:
4177 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4188 if (!Subtarget->hasDataBarrier()) {
4192 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4193 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4204 }
else if (Subtarget->preferISHSTBarriers() &&
4213 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4221 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4223 return Op.getOperand(0);
4226 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4228 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4230 return Op.getOperand(0);
4232 unsigned isData =
Op.getConstantOperandVal(4);
4233 if (Subtarget->isThumb()) {
4235 isRead = ~isRead & 1;
4236 isData = ~isData & 1;
4254 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4262 const SDLoc &dl)
const {
4264 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4266 const TargetRegisterClass *RC;
4268 RC = &ARM::tGPRRegClass;
4270 RC = &ARM::GPRRegClass;
4284 MVT::i32, dl, Root, FIN,
4290 if (!Subtarget->isLittle())
4305 const Value *OrigArg,
4306 unsigned InRegsParamRecordIdx,
4307 int ArgOffset,
unsigned ArgSize)
const {
4321 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4322 unsigned RBegin, REnd;
4327 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4332 ArgOffset = -4 * (ARM::R4 - RBegin);
4339 const TargetRegisterClass *RC =
4342 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4346 MachinePointerInfo(OrigArg, 4 * i));
4351 if (!MemOps.
empty())
4360 unsigned TotalArgRegsSaveSize,
4361 bool ForceMutable)
const {
4363 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4372 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4376bool ARMTargetLowering::splitValueIntoRegisterParts(
4378 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4380 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4385 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
4392SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4394 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4395 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4402 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
4408SDValue ARMTargetLowering::LowerFormalArguments(
4415 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4424 unsigned CurArgIdx = 0;
4436 unsigned ArgRegBegin = ARM::R4;
4437 for (
const CCValAssign &VA : ArgLocs) {
4443 if (!
Flags.isByVal())
4447 unsigned RBegin, REnd;
4449 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4455 int lastInsIndex = -1;
4459 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4462 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4466 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4467 CCValAssign &VA = ArgLocs[i];
4468 if (Ins[VA.
getValNo()].isOrigArg()) {
4469 std::advance(CurOrigArg,
4470 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4482 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4489 MVT::f64, dl, Chain, FIN,
4492 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4500 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4502 const TargetRegisterClass *RC;
4504 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4505 RC = &ARM::HPRRegClass;
4506 else if (RegVT == MVT::f32)
4507 RC = &ARM::SPRRegClass;
4508 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4509 RegVT == MVT::v4bf16)
4510 RC = &ARM::DPRRegClass;
4511 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4512 RegVT == MVT::v8bf16)
4513 RC = &ARM::QPRRegClass;
4514 else if (RegVT == MVT::i32)
4516 : &ARM::GPRRegClass;
4562 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4568 if (index != lastInsIndex)
4570 ISD::ArgFlagsTy
Flags =
Ins[index].Flags;
4576 if (
Flags.isByVal()) {
4577 assert(Ins[index].isOrigArg() &&
4578 "Byval arguments cannot be implicit");
4582 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4616 lastInsIndex = index;
4623 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4624 TotalArgRegsSaveSize);
4628 "secure entry function must not be variadic", dl.
getDebugLoc()));
4638 assert(StackAlign &&
"data layout string is missing stack alignment");
4639 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4648 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4657 return CFP->getValueAPF().isPosZero();
4661 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4664 return CFP->getValueAPF().isPosZero();
4666 }
else if (
Op->getOpcode() == ISD::BITCAST &&
4667 Op->getValueType(0) == MVT::f64) {
4682 const SDLoc &dl)
const {
4684 unsigned C = RHSC->getZExtValue();
4748 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4752 unsigned Mask =
LHS.getConstantOperandVal(1);
4754 uint64_t RHSV = RHSC->getZExtValue();
4755 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4757 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4771 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4774 LHS.getConstantOperandVal(1) < 31) {
4775 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4818 bool Signaling)
const {
4819 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4834std::pair<SDValue, SDValue>
4837 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4849 switch (
Op.getOpcode()) {
4901 return std::make_pair(
Value, OverflowCmp);
4912 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4917 EVT VT =
Op.getValueType();
4922 SDVTList VTs = DAG.
getVTList(
Op.getValueType(), MVT::i32);
4960 EVT VT =
Op.getValueType();
4961 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4964 switch (
Op.getOpcode()) {
4989 EVT VT =
Op.getValueType();
4990 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
5000 switch (
Op->getOpcode()) {
5016 switch (
Op->getOpcode()) {
5035 DAG.
getNode(NewOpcode, dl, MVT::i32,
5046 unsigned Opc =
Cond.getOpcode();
5048 if (
Cond.getResNo() == 1 &&
5056 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5057 EVT VT =
Op.getValueType();
5059 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
5068 const ConstantSDNode *CMOVTrue =
5070 const ConstantSDNode *CMOVFalse =
5073 if (CMOVTrue && CMOVFalse) {
5079 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5081 False = SelectFalse;
5082 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5088 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5089 Cond.getOperand(3), DAG);
5104 bool &swpCmpOps,
bool &swpVselOps) {
5132 swpCmpOps = !swpCmpOps;
5133 swpVselOps = !swpVselOps;
5156 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5158 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5160 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5195 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5197 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5218 EVT VT =
Op.getValueType();
5240 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5253 int64_t PosVal = std::max(Val1, Val2);
5254 int64_t NegVal = std::min(Val1, Val2);
5301 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5306 if (*K != KTmp || V != VTmp)
5317bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5319 return !Subtarget->hasVFP2Base();
5321 return !Subtarget->hasFP64();
5323 return !Subtarget->hasFullFP16();
5328 EVT VT =
Op.getValueType();
5332 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5344 if (VT == MVT::i32 &&
5364 if (
Op.getValueType().isInteger()) {
5372 LHS.getValueType() ==
RHS.getValueType()) {
5373 EVT VT =
LHS.getValueType();
5379 Shift = DAG.
getNOT(dl, Shift, VT);
5385 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5386 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5389 unsigned Opcode = 0;
5391 if (TVal == ~FVal) {
5393 }
else if (TVal == ~FVal + 1) {
5395 }
else if (TVal + 1 == FVal) {
5397 }
else if (TVal == FVal + 1) {
5428 EVT VT =
TrueVal.getValueType();
5429 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5433 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5438 if (!
RHS.getNode()) {
5444 if (
LHS.getValueType() == MVT::i32) {
5455 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5456 TrueVal.getValueType() == MVT::f32 ||
5457 TrueVal.getValueType() == MVT::f64)) {
5471 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5481 if (Subtarget->hasFPARMv8Base() &&
5483 (
TrueVal.getValueType() == MVT::f16 ||
5484 TrueVal.getValueType() == MVT::f32 ||
5485 TrueVal.getValueType() == MVT::f64)) {
5486 bool swpCmpOps =
false;
5487 bool swpVselOps =
false;
5501 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5504 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5514 if (!
N->hasOneUse())
5517 if (!
N->getNumValues())
5519 EVT VT =
Op.getValueType();
5520 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5537 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5538 Ld->getPointerInfo(), Ld->getAlign(),
5539 Ld->getMemOperand()->getFlags());
5557 DAG.
getLoad(MVT::i32, dl, Ld->getChain(),
Ptr, Ld->getPointerInfo(),
5558 Ld->getAlign(), Ld->getMemOperand()->getFlags());
5560 EVT PtrType =
Ptr.getValueType();
5563 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5564 Ld->getPointerInfo().getWithOffset(4),
5566 Ld->getMemOperand()->getFlags());
5584 bool LHSSeenZero =
false;
5586 bool RHSSeenZero =
false;
5588 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5599 if (
LHS.getValueType() == MVT::f32) {
5617 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5632 unsigned Opc =
Cond.getOpcode();
5634 !Subtarget->isThumb1Only();
5635 if (
Cond.getResNo() == 1 &&
5645 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5651 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5668 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5673 if (!
RHS.getNode()) {
5681 unsigned Opc =
LHS.getOpcode();
5683 !Subtarget->isThumb1Only();
5695 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5702 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5709 if (
LHS.getValueType() == MVT::i32) {
5715 SDNodeFlags
Flags =
Op->getFlags();
5721 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5752 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5758 Addr,
Op.getOperand(2), JTI);
5762 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5769 DAG.
getLoad(PTy, dl, Chain, Addr,
5777 EVT VT =
Op.getValueType();
5780 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5781 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5789 const EVT OpTy =
Op.getOperand(0).getValueType();
5790 if (OpTy == MVT::v4f32)
5792 else if (OpTy == MVT::v4f16 && HasFullFP16)
5794 else if (OpTy == MVT::v8f16 && HasFullFP16)
5799 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5802 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5807 EVT VT =
Op.getValueType();
5811 bool IsStrict =
Op->isStrictFPOpcode();
5812 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5814 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5827 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5828 CallOptions, Loc, Chain);
5838 Loc,
Op.getValueType(), SrcVal);
5847 EVT VT =
Op.getValueType();
5849 EVT FromVT =
Op.getOperand(0).getValueType();
5851 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5853 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5854 Subtarget->hasFP64())
5856 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5857 Subtarget->hasFullFP16())
5859 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5860 Subtarget->hasMVEFloatOps())
5862 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5863 Subtarget->hasMVEFloatOps())
5866 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5883 EVT VT =
Op.getValueType();
5886 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5892 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5893 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5894 "Invalid type for custom lowering!");
5899 if (VT == MVT::v4f32)
5900 DestVecType = MVT::v4i32;
5901 else if (VT == MVT::v4f16 && HasFullFP16)
5902 DestVecType = MVT::v4i16;
5903 else if (VT == MVT::v8f16 && HasFullFP16)
5904 DestVecType = MVT::v8i16;
5910 switch (
Op.getOpcode()) {
5922 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5927 EVT VT =
Op.getValueType();
5930 if (isUnsupportedFloatingType(VT)) {
5940 CallOptions, SDLoc(
Op)).first;
5951 EVT VT =
Op.getValueType();
5953 bool InGPR = Tmp0.
getOpcode() == ISD::BITCAST ||
5955 bool UseNEON = !InGPR && Subtarget->hasNEON();
5962 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5965 DAG.
getNode(ISD::BITCAST, dl, OpVT, Mask),
5969 if (SrcVT == MVT::f32) {
5973 DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1),
5975 }
else if (VT == MVT::f32)
5977 DAG.
getNode(ISD::BITCAST, dl, MVT::v1i64, Tmp1),
5979 Tmp0 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp0);
5980 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1);
5991 if (VT == MVT::f32) {
5992 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::v2f32, Res);
5996 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Res);
6003 if (SrcVT == MVT::f64)
6006 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp1);
6012 if (VT == MVT::f32) {
6014 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
6015 return DAG.
getNode(ISD::BITCAST, dl, MVT::f32,
6033 EVT VT =
Op.getValueType();
6035 unsigned Depth =
Op.getConstantOperandVal(0);
6037 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
6041 MachinePointerInfo());
6050 const ARMBaseRegisterInfo &ARI =
6051 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
6056 EVT VT =
Op.getValueType();
6058 unsigned Depth =
Op.getConstantOperandVal(0);
6063 MachinePointerInfo());
6071 return StringSwitch<Register>(
RegName)
6072 .Case(
"sp", ARM::SP)
6083 assert(
N->getValueType(0) == MVT::i64
6084 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6087 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6127 const APInt &APIntIndex = Index->getAPIntValue();
6129 NewIndex *= APIntIndex;
6141 SDValue BitCast = DAG.
getNode(ISD::BITCAST, dl, VecVT, ExtractSrc);
6158 EVT SrcVT =
Op.getValueType();
6159 EVT DstVT =
N->getValueType(0);
6161 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6162 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6163 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6166 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6167 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6168 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6175 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6186 return DAG.
getNode(ISD::BITCAST, dl, DstVT,
6220 return DAG.
getNode(ISD::BITCAST, dl, VT, Vmov);
6228 EVT VT =
Op.getValueType();
6271 EVT VT =
Op.getValueType();
6313 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6365 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6393 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6423 EVT VT =
N->getValueType(0);
6424 if (VT.
isVector() && ST->hasNEON()) {
6433 if (ElemTy == MVT::i8) {
6441 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6444 unsigned NumBits = ElemTy.getSizeInBits();
6456 if (ElemTy == MVT::i64) {
6469 if (!ST->hasV6T2Ops())
6478 EVT VT =
N->getValueType(0);
6481 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6482 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6483 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6484 "Unexpected type for custom ctpop lowering");
6492 unsigned EltSize = 8;
6514 while (
Op.getOpcode() == ISD::BITCAST)
6515 Op =
Op.getOperand(0);
6517 APInt SplatBits, SplatUndef;
6518 unsigned SplatBitSize;
6521 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6523 SplatBitSize > ElementBits)
6534 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6538 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6549 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6554 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6555 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6564 EVT VT =
N->getValueType(0);
6586 "unexpected vector shift opcode");
6588 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6589 unsigned VShiftOpc =
6591 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6597 EVT ShiftVT =
N->getOperand(1).getValueType();
6600 unsigned VShiftOpc =
6602 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6607 EVT VT =
N->getValueType(0);
6616 "Unknown shift to lower!");
6618 unsigned ShOpc =
N->getOpcode();
6619 if (ST->hasMVEIntegerOps()) {
6649 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6663 if (ST->isThumb1Only())
6668 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6684 bool Invert =
false;
6691 EVT VT =
Op.getValueType();
6699 assert(ST->hasMVEIntegerOps() &&
6700 "No hardware support for integer vector comparison!");
6702 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6725 Merged = DAG.
getNode(ISD::BITCAST, dl, CmpVT, Merged);
6727 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6737 switch (SetCCOpcode) {
6741 if (ST->hasMVEFloatOps()) {
6744 Invert =
true; [[fallthrough]];
6749 case ISD::SETLT: Swap =
true; [[fallthrough]];
6753 case ISD::SETLE: Swap =
true; [[fallthrough]];
6769 Result = DAG.
getNOT(dl, Result, VT);
6772 case ISD::SETUO: Invert =
true; [[fallthrough]];
6781 Result = DAG.
getNOT(dl, Result, VT);
6787 switch (SetCCOpcode) {
6790 if (ST->hasMVEIntegerOps()) {
6793 Invert =
true; [[fallthrough]];
6796 case ISD::SETLT: Swap =
true; [[fallthrough]];
6798 case ISD::SETLE: Swap =
true; [[fallthrough]];
6815 if (AndOp.getNode() && AndOp.getOpcode() == ISD::BITCAST)
6818 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6819 Op0 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(0));
6820 Op1 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(1));
6823 Result = DAG.
getNOT(dl, Result, VT);
6857 Result = DAG.
getNOT(dl, Result, VT);
6869 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6896 unsigned OpCmode, Imm;
6907 switch (SplatBitSize) {
6912 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6915 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6920 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6921 if ((SplatBits & ~0xff) == 0) {
6927 if ((SplatBits & ~0xff00) == 0) {
6930 Imm = SplatBits >> 8;
6940 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6941 if ((SplatBits & ~0xff) == 0) {
6947 if ((SplatBits & ~0xff00) == 0) {
6950 Imm = SplatBits >> 8;
6953 if ((SplatBits & ~0xff0000) == 0) {
6956 Imm = SplatBits >> 16;
6959 if ((SplatBits & ~0xff000000) == 0) {
6962 Imm = SplatBits >> 24;
6969 if ((SplatBits & ~0xffff) == 0 &&
6970 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6973 Imm = SplatBits >> 8;
6981 if ((SplatBits & ~0xffffff) == 0 &&
6982 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6985 Imm = SplatBits >> 16;
7001 unsigned ImmMask = 1;
7003 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
7004 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
7006 }
else if ((SplatBits & BitMask) != 0) {
7015 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
7029 EVT VT =
Op.getValueType();
7030 bool IsDouble = (VT == MVT::f64);
7036 if (
ST->genExecuteOnly()) {
7038 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
7039 "Unexpected architecture");
7062 if (!
ST->hasVFP3Base())
7067 if (IsDouble && !Subtarget->hasFP64())
7074 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7092 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7101 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7112 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
7129 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
7155 unsigned ExpectedElt = Imm;
7156 for (
unsigned i = 1; i < NumElts; ++i) {
7160 if (ExpectedElt == NumElts)
7163 if (M[i] < 0)
continue;
7164 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7172 bool &ReverseVEXT,
unsigned &Imm) {
7174 ReverseVEXT =
false;
7185 unsigned ExpectedElt = Imm;
7186 for (
unsigned i = 1; i < NumElts; ++i) {
7190 if (ExpectedElt == NumElts * 2) {
7195 if (M[i] < 0)
continue;
7196 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7211 return VT == MVT::v8i8 && M.size() == 8;
7216 if (Mask.size() == Elements * 2)
7217 return Index / Elements;
7218 return Mask[Index] == 0 ? 0 : 1;
7248 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7256 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7258 for (
unsigned j = 0; j < NumElts; j += 2) {
7259 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7260 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7265 if (M.size() == NumElts*2)
7280 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7283 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7285 for (
unsigned j = 0; j < NumElts; j += 2) {
7286 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7287 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7292 if (M.size() == NumElts*2)
7312 if (M.size() != NumElts && M.size() != NumElts*2)
7315 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7317 for (
unsigned j = 0; j < NumElts; ++j) {
7318 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7323 if (M.size() == NumElts*2)
7342 if (M.size() != NumElts && M.size() != NumElts*2)
7345 unsigned Half = NumElts / 2;
7346 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7348 for (
unsigned j = 0; j < NumElts; j += Half) {
7349 unsigned Idx = WhichResult;
7350 for (
unsigned k = 0; k < Half; ++k) {
7351 int MIdx = M[i + j + k];
7352 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7359 if (M.size() == NumElts*2)
7383 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7386 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7388 unsigned Idx = WhichResult * NumElts / 2;
7389 for (
unsigned j = 0; j < NumElts; j += 2) {
7390 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7391 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7397 if (M.size() == NumElts*2)
7416 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7419 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7421 unsigned Idx = WhichResult * NumElts / 2;
7422 for (
unsigned j = 0; j < NumElts; j += 2) {
7423 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7424 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7430 if (M.size() == NumElts*2)
7443 unsigned &WhichResult,
7446 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7448 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7450 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7468 if (NumElts != M.size())
7472 for (
unsigned i = 0; i != NumElts; ++i)
7473 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7482 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7490 int Ofs = Top ? 1 : 0;
7491 int Upper = SingleSource ? 0 : NumElts;
7492 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7493 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7495 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7504 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7513 unsigned Offset = Top ? 0 : 1;
7514 unsigned N = SingleSource ? 0 : NumElts;
7515 for (
unsigned i = 0; i < NumElts; i += 2) {
7516 if (M[i] >= 0 && M[i] != (
int)i)
7518 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7527 if (NumElts != M.size())
7535 unsigned Off0 = rev ? NumElts / 2 : 0;
7536 unsigned Off1 = rev ? 0 : NumElts / 2;
7537 for (
unsigned i = 0; i < NumElts; i += 2) {
7538 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7540 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7556 if (!ST->hasMVEFloatOps())
7561 if (VT != MVT::v8f16)
7582 for (
unsigned i = 1; i < 4; i++) {
7609 if (!ST->hasMVEFloatOps())
7614 if (VT != MVT::v4f32)
7630 for (
unsigned i = 1; i < 4; i++) {
7632 return Trunc.
getOpcode() == ISD::FP_EXTEND &&
7653 Val =
N->getAsZExtVal();
7655 if (ST->isThumb1Only()) {
7656 if (Val <= 255 || ~Val <= 255)
7668 EVT VT =
Op.getValueType();
7670 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7674 unsigned BitsPerBool;
7678 }
else if (NumElts == 4) {
7681 }
else if (NumElts == 8) {
7684 }
else if (NumElts == 16) {
7695 return U.get().isUndef() || U.get() == FirstOp;
7703 unsigned Bits32 = 0;
7704 for (
unsigned i = 0; i < NumElts; ++i) {
7708 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7710 Bits32 |= BoolMask << (i * BitsPerBool);
7716 for (
unsigned i = 0; i < NumElts; ++i) {
7729 if (!ST->hasMVEIntegerOps())
7733 EVT VT =
Op.getValueType();
7743 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7747 for (
unsigned I = 2;
I < NumElts;
I++) {
7763 switch (
N->getOpcode()) {
7774 return N->getOperand(1).getNode() ==
Op;
7776 switch (
N->getConstantOperandVal(0)) {
7777 case Intrinsic::arm_mve_add_predicated:
7778 case Intrinsic::arm_mve_mul_predicated:
7779 case Intrinsic::arm_mve_qadd_predicated:
7780 case Intrinsic::arm_mve_vhadd:
7781 case Intrinsic::arm_mve_hadd_predicated:
7782 case Intrinsic::arm_mve_vqdmulh:
7783 case Intrinsic::arm_mve_qdmulh_predicated:
7784 case Intrinsic::arm_mve_vqrdmulh:
7785 case Intrinsic::arm_mve_qrdmulh_predicated:
7786 case Intrinsic::arm_mve_vqdmull:
7787 case Intrinsic::arm_mve_vqdmull_predicated:
7789 case Intrinsic::arm_mve_sub_predicated:
7790 case Intrinsic::arm_mve_qsub_predicated:
7791 case Intrinsic::arm_mve_vhsub:
7792 case Intrinsic::arm_mve_hsub_predicated:
7793 return N->getOperand(2).getNode() ==
Op;
7808 EVT VT =
Op.getValueType();
7816 APInt SplatBits, SplatUndef;
7817 unsigned SplatBitSize;
7819 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7826 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7828 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7829 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7830 : SplatBitSize == 16 ? MVT::v8i16
7837 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7838 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7843 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7851 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7853 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7861 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7871 if (
ST->hasMVEIntegerOps() &&
7872 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7873 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7874 : SplatBitSize == 16 ? MVT::v8i16
7891 bool isOnlyLowElement =
true;
7892 bool usesOnlyOneValue =
true;
7893 bool hasDominantValue =
false;
7898 DenseMap<SDValue, unsigned> ValueCounts;
7900 for (
unsigned i = 0; i < NumElts; ++i) {
7905 isOnlyLowElement =
false;
7909 unsigned &
Count = ValueCounts[
V];
7912 if (++
Count > (NumElts / 2)) {
7913 hasDominantValue =
true;
7917 if (ValueCounts.
size() != 1)
7918 usesOnlyOneValue =
false;
7919 if (!
Value.getNode() && !ValueCounts.
empty())
7922 if (ValueCounts.
empty())
7934 if (hasDominantValue && EltSize <= 32) {
7943 ConstantSDNode *constIndex;
7950 if (VT !=
Value->getOperand(0).getValueType()) {
7963 if (!usesOnlyOneValue) {
7966 for (
unsigned I = 0;
I < NumElts; ++
I) {
7971 Ops.push_back(
Op.getOperand(
I));
7981 assert(FVT == MVT::f32 || FVT == MVT::f16);
7982 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7983 for (
unsigned i = 0; i < NumElts; ++i)
7984 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, IVT,
7988 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7990 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
7992 if (usesOnlyOneValue) {
8019 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
8039 if (EltSize >= 32) {
8045 for (
unsigned i = 0; i < NumElts; ++i)
8046 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, EltVT,
Op.getOperand(i)));
8048 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8059 for (
unsigned i = 0 ; i < NumElts; ++i) {
8078 EVT VT =
Op.getValueType();
8081 struct ShuffleSourceInfo {
8083 unsigned MinElt = std::numeric_limits<unsigned>::max();
8084 unsigned MaxElt = 0;
8094 int WindowScale = 1;
8096 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8104 for (
unsigned i = 0; i < NumElts; ++i) {
8119 SDValue SourceVec =
V.getOperand(0);
8121 if (Source == Sources.
end())
8125 unsigned EltNo =
V.getConstantOperandVal(1);
8132 if (Sources.
size() > 2)
8138 for (
auto &Source : Sources) {
8139 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8140 if (SrcEltTy.
bitsLT(SmallestEltTy))
8141 SmallestEltTy = SrcEltTy;
8143 unsigned ResMultiplier =
8151 for (
auto &Src : Sources) {
8152 EVT SrcVT = Src.ShuffleVec.getValueType();
8156 if (SrcVTSize == VTSize)
8165 if (SrcVTSize < VTSize) {
8166 if (2 * SrcVTSize != VTSize)
8172 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8176 if (SrcVTSize != 2 * VTSize)
8179 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8184 if (Src.MinElt >= NumSrcElts) {
8189 Src.WindowBase = -NumSrcElts;
8190 }
else if (Src.MaxElt < NumSrcElts) {
8207 Src.WindowBase = -Src.MinElt;
8214 for (
auto &Src : Sources) {
8215 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8216 if (SrcEltTy == SmallestEltTy)
8221 Src.WindowBase *= Src.WindowScale;
8226 for (
auto Src : Sources)
8227 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8235 if (
Entry.isUndef())
8244 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8247 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8251 int *LaneMask = &
Mask[i * ResMultiplier];
8253 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8254 ExtractBase += NumElts * (Src - Sources.begin());
8255 for (
int j = 0;
j < LanesDefined; ++
j)
8256 LaneMask[j] = ExtractBase + j;
8262 assert(Sources.size() <= 2 &&
"Too many sources!");
8265 for (
unsigned i = 0; i < Sources.size(); ++i)
8294 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8314 unsigned PFIndexes[4];
8315 for (
unsigned i = 0; i != 4; ++i) {
8319 PFIndexes[i] = M[i];
8323 unsigned PFTableIndex =
8324 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8326 unsigned Cost = (PFEntry >> 30);
8332 bool ReverseVEXT, isV_UNDEF;
8333 unsigned Imm, WhichResult;
8336 if (EltSize >= 32 ||
8343 else if (Subtarget->hasNEON() &&
8348 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8351 else if (Subtarget->hasMVEIntegerOps() &&
8355 else if (Subtarget->hasMVEIntegerOps() &&
8369 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8370 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8371 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8374 if (LHSID == (1*9+2)*9+3)
return LHS;
8375 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8432 for (
int I : ShuffleMask)
8445 EVT VT =
Op.getValueType();
8447 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8448 "Expect an v8i16/v16i8 type");
8454 std::vector<int> NewMask;
8458 NewMask.push_back(i);
8498 if (VT != MVT::v16i1)
8509 return DAG.
getNode(ISD::BITCAST, dl, NewVT, PredAsVector);
8514 EVT VT =
Op.getValueType();
8518 assert(ST->hasMVEIntegerOps() &&
8519 "No support for vector shuffle of boolean predicates");
8545 "Expected identical vector type in expanded i1 shuffle!");
8549 PredAsVector2, ShuffleMask);
8554 if (VT == MVT::v2i1) {
8571 EVT VT =
Op.getValueType();
8575 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8576 "Unexpected vector type");
8578 int QuarterSize = NumElts / 4;
8587 for (
int i = 0; i <
Length; i++) {
8588 if (ShuffleMask[Start + i] >= 0) {
8589 if (ShuffleMask[Start + i] %
Length != i)
8591 MovIdx = ShuffleMask[Start + i] /
Length;
8599 for (
int i = 1; i <
Length; i++) {
8600 if (ShuffleMask[Start + i] >= 0 &&
8601 (ShuffleMask[Start + i] /
Length != MovIdx ||
8602 ShuffleMask[Start + i] %
Length != i))
8608 for (
int Part = 0; Part < 4; ++Part) {
8610 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8624 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8629 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8631 for (
int Part = 0; Part < 4; ++Part)
8632 for (
int i = 0; i < QuarterSize; i++)
8634 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8636 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8639 for (
int Part = 0; Part < 4; ++Part)
8655 EVT VT =
Op.getValueType();
8667 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8671 if (Mask[i] != i + BaseOffset) {
8672 if (OffElement == -1)
8678 return NonUndef > 2 && OffElement != -1;
8682 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8684 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8695 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8706 EVT VT =
Op.getValueType();
8710 if (ST->hasMVEIntegerOps() && EltSize == 1)
8721 if (EltSize <= 32) {
8725 if (Lane == -1) Lane = 0;
8736 bool IsScalarToVector =
true;
8739 IsScalarToVector =
false;
8742 if (IsScalarToVector)
8749 bool ReverseVEXT =
false;
8751 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8775 unsigned WhichResult = 0;
8776 bool isV_UNDEF =
false;
8777 if (ST->hasNEON()) {
8779 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8786 if (ST->hasMVEIntegerOps()) {
8821 }) &&
"Unexpected shuffle index into UNDEF operand!");
8824 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8827 assert((WhichResult == 0) &&
8828 "In-place shuffle of concat can only have one result!");
8837 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8841 for (
bool Top : {
false,
true}) {
8842 for (
bool SingleSource : {
false,
true}) {
8843 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8848 SingleSource ? V1 : V2);
8864 unsigned PFIndexes[4];
8865 for (
unsigned i = 0; i != 4; ++i) {
8866 if (ShuffleMask[i] < 0)
8869 PFIndexes[i] = ShuffleMask[i];
8873 unsigned PFTableIndex =
8874 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8876 unsigned Cost = (PFEntry >> 30);
8882 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8883 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8893 if (EltSize >= 32) {
8898 V1 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V1);
8899 V2 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V2);
8901 for (
unsigned i = 0; i < NumElts; ++i) {
8902 if (ShuffleMask[i] < 0)
8906 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8911 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8914 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8918 if (ST->hasNEON() && VT == MVT::v8i8)
8922 if (ST->hasMVEIntegerOps())
8931 EVT VecVT =
Op.getOperand(0).getValueType();
8934 assert(ST->hasMVEIntegerOps() &&
8935 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8939 unsigned Lane =
Op.getConstantOperandVal(2);
8940 unsigned LaneWidth =
8942 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8960 if (Subtarget->hasMVEIntegerOps() &&
8961 Op.getValueType().getScalarSizeInBits() == 1)
8985 IVecIn, IElt, Lane);
8986 return DAG.
getNode(ISD::BITCAST, dl, VecVT, IVecOut);
8994 EVT VecVT =
Op.getOperand(0).getValueType();
8997 assert(ST->hasMVEIntegerOps() &&
8998 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9002 unsigned Lane =
Op.getConstantOperandVal(1);
9003 unsigned LaneWidth =
9034 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
9035 "Unexpected custom CONCAT_VECTORS lowering");
9037 "Unexpected custom CONCAT_VECTORS lowering");
9038 assert(ST->hasMVEIntegerOps() &&
9039 "CONCAT_VECTORS lowering only supported for MVE");
9043 EVT Op2VT = V2.getValueType();
9044 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9045 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9046 "Unexpected i1 concat operations!");
9059 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9073 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9074 EVT NewVT = NewV.getValueType();
9075 EVT ConcatVT = ConVec.getValueType();
9076 unsigned ExtScale = 1;
9077 if (NewVT == MVT::v2f64) {
9091 ConVec = ExtractInto(NewV1, ConVec, j);
9092 ConVec = ExtractInto(NewV2, ConVec, j);
9102 while (ConcatOps.
size() > 1) {
9103 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
9106 ConcatOps[
I / 2] = ConcatPair(V1, V2);
9110 return ConcatOps[0];
9115 EVT VT =
Op->getValueType(0);
9121 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9122 "unexpected CONCAT_VECTORS");
9129 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op0),
9133 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op1),
9135 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Val);
9143 EVT VT =
Op.getValueType();
9149 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9150 assert(ST->hasMVEIntegerOps() &&
9151 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9161 EVT SubVT = MVT::v4i32;
9163 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9178 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9194 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9195 EVT VT =
N->getValueType(0);
9196 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9197 "Expected a vector i1 type!");
9199 EVT FromVT =
Op.getValueType();
9210 if (!Subtarget->hasMVEIntegerOps())
9213 EVT ToVT =
N->getValueType(0);
9256 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9258 EVT FromVT =
N->getOperand(0).getValueType();
9259 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9270 if (!Subtarget->hasMVEIntegerOps())
9275 EVT ToVT =
N->getValueType(0);
9276 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9279 EVT FromVT =
Op.getValueType();
9280 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9291 SDValue Ext1 = Ext.getValue(1);
9294 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9295 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9307 EVT VT =
N->getValueType(0);
9308 if (VT == MVT::v2i64 &&
N->getOpcode() == ISD::BITCAST) {
9309 SDNode *BVN =
N->getOperand(0).getNode();
9314 unsigned HiElt = 1 - LoElt;
9319 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9335 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9336 SDNode *Elt =
N->getOperand(i).getNode();
9339 unsigned HalfSize = EltSize / 2;
9341 if (!
isIntN(HalfSize,
C->getSExtValue()))
9344 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9383 switch (OrigSimpleTy) {
9399 unsigned ExtOpcode) {
9422 if (ExtendedTy == LD->getMemoryVT())
9423 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9424 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9425 LD->getMemOperand()->getFlags());
9431 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9432 LD->getMemoryVT(), LD->getAlign(),
9433 LD->getMemOperand()->getFlags());
9446 N->getOperand(0)->getValueType(0),
9452 "Expected extending load");
9458 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9466 if (
N->getOpcode() == ISD::BITCAST) {
9467 SDNode *BVN =
N->getOperand(0).getNode();
9469 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9477 EVT VT =
N->getValueType(0);
9483 for (
unsigned i = 0; i != NumElts; ++i) {
9484 const APInt &CInt =
N->getConstantOperandAPInt(i);
9493 unsigned Opcode =
N->getOpcode();
9495 SDNode *N0 =
N->getOperand(0).getNode();
9496 SDNode *N1 =
N->getOperand(1).getNode();
9504 unsigned Opcode =
N->getOpcode();
9506 SDNode *N0 =
N->getOperand(0).getNode();
9507 SDNode *N1 =
N->getOperand(1).getNode();
9517 EVT VT =
Op.getValueType();
9519 "unexpected type for custom-lowering ISD::MUL");
9520 SDNode *N0 =
Op.getOperand(0).getNode();
9521 SDNode *N1 =
Op.getOperand(1).getNode();
9522 unsigned NewOpc = 0;
9526 if (isN0SExt && isN1SExt)
9531 if (isN0ZExt && isN1ZExt)
9533 else if (isN1SExt || isN1ZExt) {
9550 if (VT == MVT::v2i64)
9567 "unexpected types for extended operands to VMULL");
9568 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9584 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N00), Op1),
9586 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N01), Op1));
9603 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9610 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32,
X);
9613 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32,
X);
9637 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9640 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9648 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9651 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9661 EVT VT =
Op.getValueType();
9662 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9663 "unexpected type for custom-lowering ISD::SDIV");
9670 if (VT == MVT::v8i8) {
9698 EVT VT =
Op.getValueType();
9699 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9700 "unexpected type for custom-lowering ISD::UDIV");
9707 if (VT == MVT::v8i8) {
9746 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9749 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9753 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9761 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9764 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9774 EVT VT =
N->getValueType(0);
9788 Op.getOperand(1), Carry);
9802 Op.getOperand(1), Carry);
9817 assert(Subtarget->isTargetDarwin());
9836 if (ShouldUseSRet) {
9838 const uint64_t ByteSize =
DL.getTypeAllocSize(RetTy);
9839 const Align StackAlign =
DL.getPrefTypeAlign(RetTy);
9844 Entry.IsSExt =
false;
9845 Entry.IsZExt =
false;
9846 Entry.IsSRet =
true;
9847 Args.push_back(Entry);
9851 Args.emplace_back(Arg, ArgTy);
9854 (ArgVT == MVT::f64) ? RTLIB::SINCOS_STRET_F64 : RTLIB::SINCOS_STRET_F32;
9859 TargetLowering::CallLoweringInfo CLI(DAG);
9862 .
setCallee(CC, RetTy, Callee, std::move(Args))
9864 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
9867 return CallResult.first;
9870 DAG.
getLoad(ArgVT, dl, CallResult.second, SRet, MachinePointerInfo());
9878 SDVTList Tys = DAG.
getVTList(ArgVT, ArgVT);
9886 EVT VT =
Op.getValueType();
9887 assert((VT == MVT::i32 || VT == MVT::i64) &&
9888 "unexpected type for custom lowering DIV");
9894 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9896 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9903 for (
auto AI : {1, 0}) {
9905 Args.emplace_back(Operand,
9913 ES, std::move(Args));
9923ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9931 const bool MinSize =
ST.hasMinSize();
9932 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9933 :
ST.hasDivideInARMMode();
9937 if (
N->getOperand(0).getValueType().isVector())
9942 if (!(MinSize && HasDivide))
9955 if (Divisor.
sgt(128))
9963 assert(
Op.getValueType() == MVT::i32 &&
9964 "unexpected type for custom lowering DIV");
9970 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9976 if (
N->getValueType(0) == MVT::i32)
9984void ARMTargetLowering::ExpandDIV_Windows(
9989 assert(
Op.getValueType() == MVT::i64 &&
9990 "unexpected type for custom lowering DIV");
10007 EVT MemVT = LD->getMemoryVT();
10008 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10009 MemVT == MVT::v16i1) &&
10010 "Expected a predicate type!");
10011 assert(MemVT ==
Op.getValueType());
10013 "Expected a non-extending load");
10014 assert(LD->isUnindexed() &&
"Expected a unindexed load");
10028 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
10030 LD->getMemOperand());
10037 if (MemVT != MVT::v16i1)
10046 EVT MemVT =
LD->getMemoryVT();
10047 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10049 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10050 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
10051 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10055 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10065 EVT MemVT = ST->getMemoryVT();
10066 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10067 MemVT == MVT::v16i1) &&
10068 "Expected a predicate type!");
10069 assert(MemVT == ST->getValue().getValueType());
10070 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10071 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10076 SDValue Build = ST->getValue();
10077 if (MemVT != MVT::v16i1) {
10096 ST->getChain(), dl, GRP, ST->getBasePtr(),
10098 ST->getMemOperand());
10104 EVT MemVT = ST->getMemoryVT();
10105 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10107 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10123 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10124 MemVT, ST->getMemOperand());
10125 }
else if (Subtarget->hasMVEIntegerOps() &&
10126 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10127 MemVT == MVT::v16i1))) {
10142 MVT VT =
Op.getSimpleValueType();
10144 SDValue PassThru =
N->getPassThru();
10155 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10156 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10157 N->getExtensionType(),
N->isExpandingLoad());
10159 bool PassThruIsCastZero = (PassThru.
getOpcode() == ISD::BITCAST ||
10162 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10169 if (!ST->hasMVEIntegerOps())
10173 unsigned BaseOpcode = 0;
10174 switch (
Op->getOpcode()) {
10176 case ISD::VECREDUCE_FADD: BaseOpcode =
ISD::FADD;
break;
10177 case ISD::VECREDUCE_FMUL: BaseOpcode =
ISD::FMUL;
break;
10178 case ISD::VECREDUCE_MUL: BaseOpcode =
ISD::MUL;
break;
10179 case ISD::VECREDUCE_AND: BaseOpcode =
ISD::AND;
break;
10180 case ISD::VECREDUCE_OR: BaseOpcode =
ISD::OR;
break;
10181 case ISD::VECREDUCE_XOR: BaseOpcode =
ISD::XOR;
break;
10182 case ISD::VECREDUCE_FMAX: BaseOpcode = ISD::FMAXNUM;
break;
10183 case ISD::VECREDUCE_FMIN: BaseOpcode = ISD::FMINNUM;
break;
10190 unsigned NumActiveLanes = NumElts;
10192 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10193 NumActiveLanes == 2) &&
10194 "Only expected a power 2 vector size");
10198 while (NumActiveLanes > 4) {
10201 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10202 NumActiveLanes /= 2;
10206 if (NumActiveLanes == 4) {
10216 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10217 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10218 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10224 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10228 if (EltVT !=
Op->getValueType(0))
10235 if (!ST->hasMVEFloatOps())
10242 if (!ST->hasNEON())
10250 unsigned PairwiseIntrinsic = 0;
10251 switch (
Op->getOpcode()) {
10254 case ISD::VECREDUCE_UMIN:
10255 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10257 case ISD::VECREDUCE_UMAX:
10258 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10260 case ISD::VECREDUCE_SMIN:
10261 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10263 case ISD::VECREDUCE_SMAX:
10264 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10270 unsigned NumActiveLanes = NumElts;
10272 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10273 NumActiveLanes == 2) &&
10274 "Only expected a power 2 vector size");
10280 VT =
Lo.getValueType();
10282 NumActiveLanes /= 2;
10286 while (NumActiveLanes > 1) {
10288 NumActiveLanes /= 2;
10295 if (EltVT !=
Op.getValueType()) {
10296 unsigned Extend = 0;
10297 switch (
Op->getOpcode()) {
10300 case ISD::VECREDUCE_UMIN:
10301 case ISD::VECREDUCE_UMAX:
10304 case ISD::VECREDUCE_SMIN:
10305 case ISD::VECREDUCE_SMAX:
10309 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10354 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10360 SDLoc dl(V.getNode());
10361 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10371 assert(
N->getValueType(0) == MVT::i64 &&
10372 "AtomicCmpSwap on types less than 64 should be legal");
10381 ARM::CMP_SWAP_64,
SDLoc(
N),
10382 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10401 EVT VT =
Op.getValueType();
10410 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10412 Chain, IsSignaling);
10413 if (!
RHS.getNode()) {
10429 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10431 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10432 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10449 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10452 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10465 if (!IsSigned && Subtarget->isThumb1Only()) {
10483 Sub1Result, Sub1Result, Flags1);
10498 if (
Op.getValueType() != MVT::i32)
10521 bool CanUseAdd =
false;
10562 GTCondValue, Flags);
10567 LTCondValue, Flags);
10569 if (
Op.getValueType() != MVT::i32)
10577 switch (
Op.getOpcode()) {
10586 case ISD::BRCOND:
return LowerBRCOND(
Op, DAG);
10587 case ISD::BR_CC:
return LowerBR_CC(
Op, DAG);
10588 case ISD::BR_JT:
return LowerBR_JT(
Op, DAG);
10609 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10613 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10614 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10634 case ISD::SET_ROUNDING:
return LowerSET_ROUNDING(
Op, DAG);
10635 case ISD::SET_FPMODE:
10636 return LowerSET_FPMODE(
Op, DAG);
10637 case ISD::RESET_FPMODE:
10638 return LowerRESET_FPMODE(
Op, DAG);
10641 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10642 return LowerDIV_Windows(
Op, DAG,
true);
10645 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10646 return LowerDIV_Windows(
Op, DAG,
false);
10653 return LowerSignedALUO(
Op, DAG);
10656 return LowerUnsignedALUO(
Op, DAG);
10668 case ISD::VECREDUCE_MUL:
10669 case ISD::VECREDUCE_AND:
10670 case ISD::VECREDUCE_OR:
10671 case ISD::VECREDUCE_XOR:
10673 case ISD::VECREDUCE_FADD:
10674 case ISD::VECREDUCE_FMUL:
10675 case ISD::VECREDUCE_FMIN:
10676 case ISD::VECREDUCE_FMAX:
10678 case ISD::VECREDUCE_UMIN:
10679 case ISD::VECREDUCE_UMAX:
10680 case ISD::VECREDUCE_SMIN:
10681 case ISD::VECREDUCE_SMAX:
10683 case ISD::ATOMIC_LOAD:
10685 case ISD::FSINCOS:
return LowerFSINCOS(
Op, DAG);
10688 case ISD::DYNAMIC_STACKALLOC:
10689 if (Subtarget->isTargetWindows())
10690 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10695 case ISD::FP_EXTEND:
return LowerFP_EXTEND(
Op, DAG);
10699 return LowerSPONENTRY(
Op, DAG);
10700 case ISD::FP_TO_BF16:
10701 return LowerFP_TO_BF16(
Op, DAG);
10705 return LowerCMP(
Op, DAG);
10711 unsigned IntNo =
N->getConstantOperandVal(0);
10713 if (IntNo == Intrinsic::arm_smlald)
10715 else if (IntNo == Intrinsic::arm_smlaldx)
10717 else if (IntNo == Intrinsic::arm_smlsld)
10719 else if (IntNo == Intrinsic::arm_smlsldx)
10726 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10730 N->getOperand(1),
N->getOperand(2),
10742 switch (
N->getOpcode()) {
10749 Res = ExpandBITCAST(
N, DAG, Subtarget);
10758 Res = LowerREM(
N, DAG);
10762 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10773 case ISD::READCYCLECOUNTER:
10778 assert(Subtarget->isTargetWindows() &&
"can only expand DIV on Windows");
10781 case ISD::ATOMIC_CMP_SWAP:
10816 "ROPI/RWPI not currently supported with SjLj");
10825 bool isThumb = Subtarget->isThumb();
10826 bool isThumb2 = Subtarget->
isThumb2();
10829 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10835 : &ARM::GPRRegClass;
10853 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10859 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10865 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10883 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10888 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10893 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10898 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10904 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10919 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10925 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10941 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10948 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10949 : &ARM::GPRnopcRegClass;
10953 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10954 unsigned MaxCSNum = 0;
10955 for (MachineBasicBlock &BB : *MF) {
10961 for (MachineInstr &
II : BB) {
10962 if (!
II.isEHLabel())
10965 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10966 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10968 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10969 for (
unsigned Idx : CallSiteIdxs) {
10970 CallSiteNumToLPad[Idx].push_back(&BB);
10971 MaxCSNum = std::max(MaxCSNum, Idx);
10978 std::vector<MachineBasicBlock*> LPadList;
10979 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10980 LPadList.reserve(CallSiteNumToLPad.
size());
10981 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10982 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10983 for (MachineBasicBlock *
MBB : MBBList) {
10984 LPadList.push_back(
MBB);
10989 assert(!LPadList.empty() &&
10990 "No landing pad destinations for the dispatch jump table!");
10993 MachineJumpTableInfo *JTI =
11000 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
11003 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
11005 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
11008 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
11012 MF->insert(MF->end(), DispatchBB);
11013 MF->insert(MF->end(), DispContBB);
11014 MF->insert(MF->end(), TrapBB);
11018 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11020 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
11024 MachineInstrBuilder MIB;
11025 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11027 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
11037 unsigned NumLPads = LPadList.size();
11038 if (Subtarget->isThumb2()) {
11039 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11040 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11046 if (NumLPads < 256) {
11047 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11049 .
addImm(LPadList.size())
11052 Register VReg1 =
MRI->createVirtualRegister(TRC);
11053 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11054 .
addImm(NumLPads & 0xFFFF)
11057 unsigned VReg2 = VReg1;
11058 if ((NumLPads & 0xFFFF0000) != 0) {
11059 VReg2 =
MRI->createVirtualRegister(TRC);
11060 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11066 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11072 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11077 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11078 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11082 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11083 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11090 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11094 }
else if (Subtarget->isThumb()) {
11095 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11096 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11102 if (NumLPads < 256) {
11103 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11108 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11113 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11114 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11116 Register VReg1 =
MRI->createVirtualRegister(TRC);
11117 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11121 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11127 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11132 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
11133 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11139 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11140 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11144 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11145 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11151 MachineMemOperand *JTMMOLd =
11155 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11156 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11162 unsigned NewVReg6 = NewVReg5;
11163 if (IsPositionIndependent) {
11164 NewVReg6 =
MRI->createVirtualRegister(TRC);
11165 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11172 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11176 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11177 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11183 if (NumLPads < 256) {
11184 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11188 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11189 Register VReg1 =
MRI->createVirtualRegister(TRC);
11190 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11191 .
addImm(NumLPads & 0xFFFF)
11194 unsigned VReg2 = VReg1;
11195 if ((NumLPads & 0xFFFF0000) != 0) {
11196 VReg2 =
MRI->createVirtualRegister(TRC);
11197 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11203 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11208 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11213 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11214 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11216 Register VReg1 =
MRI->createVirtualRegister(TRC);
11217 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11222 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11233 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11234 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11239 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11240 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11244 MachineMemOperand *JTMMOLd =
11247 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11248 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11255 if (IsPositionIndependent) {
11256 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11261 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11268 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11269 for (MachineBasicBlock *CurMBB : LPadList) {
11270 if (SeenMBBs.
insert(CurMBB).second)
11277 for (MachineBasicBlock *BB : InvokeBBs) {
11281 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11282 while (!Successors.empty()) {
11283 MachineBasicBlock *SMBB = Successors.pop_back_val();
11285 BB->removeSuccessor(SMBB);
11291 BB->normalizeSuccProbs();
11298 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11299 if (!
II->isCall())
continue;
11301 DenseSet<unsigned> DefRegs;
11303 OI =
II->operands_begin(), OE =
II->operands_end();
11305 if (!OI->isReg())
continue;
11306 DefRegs.
insert(OI->getReg());
11309 MachineInstrBuilder MIB(*MF, &*
II);
11311 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11312 unsigned Reg = SavedRegs[i];
11313 if (Subtarget->isThumb2() &&
11314 !ARM::tGPRRegClass.contains(
Reg) &&
11315 !ARM::hGPRRegClass.contains(
Reg))
11317 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11319 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11331 for (MachineBasicBlock *MBBLPad : MBBLPads)
11332 MBBLPad->setIsEHPad(
false);
11335 MI.eraseFromParent();
11348static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11350 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11351 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11353 return LdSize == 4 ? ARM::tLDRi
11354 : LdSize == 2 ? ARM::tLDRHi
11355 : LdSize == 1 ? ARM::tLDRBi : 0;
11357 return LdSize == 4 ? ARM::t2LDR_POST
11358 : LdSize == 2 ? ARM::t2LDRH_POST
11359 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11360 return LdSize == 4 ? ARM::LDR_POST_IMM
11361 : LdSize == 2 ? ARM::LDRH_POST
11362 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11367static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11369 return StSize == 16 ? ARM::VST1q32wb_fixed
11370 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11372 return StSize == 4 ? ARM::tSTRi
11373 : StSize == 2 ? ARM::tSTRHi
11374 : StSize == 1 ? ARM::tSTRBi : 0;
11376 return StSize == 4 ? ARM::t2STR_POST
11377 : StSize == 2 ? ARM::t2STRH_POST
11378 : StSize == 1 ? ARM::t2STRB_POST : 0;
11379 return StSize == 4 ? ARM::STR_POST_IMM
11380 : StSize == 2 ? ARM::STRH_POST
11381 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11388 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11389 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11390 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11391 assert(LdOpc != 0 &&
"Should have a load opcode");
11398 }
else if (IsThumb1) {
11404 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11409 }
else if (IsThumb2) {
11429 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11430 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11431 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11432 assert(StOpc != 0 &&
"Should have a store opcode");
11434 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11439 }
else if (IsThumb1) {
11446 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11451 }
else if (IsThumb2) {
11452 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11458 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11473 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11479 unsigned SizeVal =
MI.getOperand(2).getImm();
11480 unsigned Alignment =
MI.getOperand(3).getImm();
11485 unsigned UnitSize = 0;
11486 const TargetRegisterClass *TRC =
nullptr;
11487 const TargetRegisterClass *VecTRC =
nullptr;
11489 bool IsThumb1 = Subtarget->isThumb1Only();
11490 bool IsThumb2 = Subtarget->isThumb2();
11491 bool IsThumb = Subtarget->isThumb();
11493 if (Alignment & 1) {
11495 }
else if (Alignment & 2) {
11500 Subtarget->hasNEON()) {
11501 if ((Alignment % 16 == 0) && SizeVal >= 16)
11503 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11512 bool IsNeon = UnitSize >= 8;
11513 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11515 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11516 : UnitSize == 8 ? &ARM::DPRRegClass
11519 unsigned BytesLeft = SizeVal % UnitSize;
11520 unsigned LoopSize = SizeVal - BytesLeft;
11522 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11526 unsigned srcIn = src;
11527 unsigned destIn = dest;
11528 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11529 Register srcOut =
MRI.createVirtualRegister(TRC);
11530 Register destOut =
MRI.createVirtualRegister(TRC);
11531 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11533 IsThumb1, IsThumb2);
11535 IsThumb1, IsThumb2);
11543 for (
unsigned i = 0; i < BytesLeft; i++) {
11544 Register srcOut =
MRI.createVirtualRegister(TRC);
11545 Register destOut =
MRI.createVirtualRegister(TRC);
11546 Register scratch =
MRI.createVirtualRegister(TRC);
11548 IsThumb1, IsThumb2);
11550 IsThumb1, IsThumb2);
11554 MI.eraseFromParent();
11580 MF->
insert(It, loopMBB);
11581 MF->
insert(It, exitMBB);
11584 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11594 Register varEnd =
MRI.createVirtualRegister(TRC);
11595 if (Subtarget->useMovt()) {
11596 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11599 }
else if (Subtarget->genExecuteOnly()) {
11600 assert(IsThumb &&
"Non-thumb expected to have used movt");
11609 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11610 MachineMemOperand *CPMMO =
11634 MachineBasicBlock *entryBB = BB;
11636 Register varLoop =
MRI.createVirtualRegister(TRC);
11637 Register varPhi =
MRI.createVirtualRegister(TRC);
11638 Register srcLoop =
MRI.createVirtualRegister(TRC);
11639 Register srcPhi =
MRI.createVirtualRegister(TRC);
11640 Register destLoop =
MRI.createVirtualRegister(TRC);
11641 Register destPhi =
MRI.createVirtualRegister(TRC);
11649 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11655 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11657 IsThumb1, IsThumb2);
11659 IsThumb1, IsThumb2);
11663 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11669 MachineInstrBuilder MIB =
11671 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11680 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11689 auto StartOfExit = exitMBB->
begin();
11693 unsigned srcIn = srcLoop;
11694 unsigned destIn = destLoop;
11695 for (
unsigned i = 0; i < BytesLeft; i++) {
11696 Register srcOut =
MRI.createVirtualRegister(TRC);
11697 Register destOut =
MRI.createVirtualRegister(TRC);
11698 Register scratch =
MRI.createVirtualRegister(TRC);
11699 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11700 IsThumb1, IsThumb2);
11701 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11702 IsThumb1, IsThumb2);
11707 MI.eraseFromParent();
11715 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11718 assert(Subtarget->isTargetWindows() &&
11719 "__chkstk is only supported on Windows");
11720 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11740 switch (TM.getCodeModel()) {
11782 MI.eraseFromParent();
11791 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11806 .
addReg(
MI.getOperand(0).getReg())
11814 MI.eraseFromParent();
11838 if (miI == BB->
end()) {
11840 if (Succ->isLiveIn(ARM::CPSR))
11846 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11858 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11859 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11865 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11866 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11872 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11873 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11876 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11877 .
addUse(TotalIterationsReg)
11884 return TotalIterationsReg;
11895 Register TotalIterationsReg,
bool IsMemcpy) {
11902 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11903 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11904 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11912 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11913 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11914 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11921 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11922 Register RemainingLoopIterationsReg =
11923 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11924 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11925 .
addUse(TotalIterationsReg)
11927 .
addUse(RemainingLoopIterationsReg)
11931 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11932 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11933 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11934 .
addUse(ElementCountReg)
11936 .
addUse(RemainingElementsReg)
11940 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11941 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11942 .
addUse(PredCounterPhiReg)
11947 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11948 .
addUse(PredCounterPhiReg)
11956 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11957 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11966 SrcValueReg = OpSrcReg;
11968 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11979 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11980 .
addUse(LoopCounterPhiReg)
11983 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11984 .
addUse(RemainingLoopIterationsReg)
11997 bool isThumb2 = Subtarget->isThumb2();
11998 switch (
MI.getOpcode()) {
12005 case ARM::tLDR_postidx: {
12009 .
add(
MI.getOperand(2))
12010 .
add(
MI.getOperand(3))
12011 .
add(
MI.getOperand(4))
12012 .
add(
MI.getOperand(0))
12014 MI.eraseFromParent();
12018 case ARM::MVE_MEMCPYLOOPINST:
12019 case ARM::MVE_MEMSETLOOPINST: {
12049 Register OpDestReg =
MI.getOperand(0).getReg();
12050 Register OpSrcReg =
MI.getOperand(1).getReg();
12051 Register OpSizeReg =
MI.getOperand(2).getReg();
12071 if (TpExit == BB) {
12073 "block containing memcpy/memset Pseudo");
12086 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12088 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12091 Properties.resetNoPHIs();
12103 MI.eraseFromParent();
12113 case ARM::t2STR_preidx:
12114 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12116 case ARM::t2STRB_preidx:
12117 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12119 case ARM::t2STRH_preidx:
12120 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12123 case ARM::STRi_preidx:
12124 case ARM::STRBi_preidx: {
12125 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12126 : ARM::STRB_PRE_IMM;
12128 unsigned Offset =
MI.getOperand(4).getImm();
12136 .
add(
MI.getOperand(0))
12137 .
add(
MI.getOperand(1))
12138 .
add(
MI.getOperand(2))
12140 .
add(
MI.getOperand(5))
12141 .
add(
MI.getOperand(6))
12143 MI.eraseFromParent();
12146 case ARM::STRr_preidx:
12147 case ARM::STRBr_preidx:
12148 case ARM::STRH_preidx: {
12150 switch (
MI.getOpcode()) {
12152 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12153 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12154 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12159 MI.eraseFromParent();
12163 case ARM::tMOVCCr_pseudo: {
12181 F->insert(It, copy0MBB);
12182 F->insert(It, sinkMBB);
12185 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12191 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12207 .
addImm(
MI.getOperand(3).getImm())
12208 .
addReg(
MI.getOperand(4).getReg());
12223 .
addReg(
MI.getOperand(1).getReg())
12225 .
addReg(
MI.getOperand(2).getReg())
12228 MI.eraseFromParent();
12233 case ARM::BCCZi64: {
12239 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12244 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12248 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12254 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12258 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12268 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12277 MI.eraseFromParent();
12281 case ARM::Int_eh_sjlj_setjmp:
12282 case ARM::Int_eh_sjlj_setjmp_nofp:
12283 case ARM::tInt_eh_sjlj_setjmp:
12284 case ARM::t2Int_eh_sjlj_setjmp:
12285 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12288 case ARM::Int_eh_sjlj_setup_dispatch:
12289 EmitSjLjDispatchBlock(
MI, BB);
12312 Fn->
insert(BBI, SinkBB);
12315 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12319 Register ABSSrcReg =
MI.getOperand(1).getReg();
12320 Register ABSDstReg =
MI.getOperand(0).getReg();
12321 bool ABSSrcKIll =
MI.getOperand(1).isKill();
12322 bool isThumb2 = Subtarget->isThumb2();
12326 Register NewRsbDstReg =
MRI.createVirtualRegister(
12327 isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRRegClass);
12341 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12348 TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)).
addMBB(SinkBB)
12355 TII->get(isThumb2 ? ARM::t2RSBri : ARM::RSBri), NewRsbDstReg)
12364 TII->get(ARM::PHI), ABSDstReg)
12369 MI.eraseFromParent();
12374 case ARM::COPY_STRUCT_BYVAL_I32:
12376 return EmitStructByval(
MI, BB);
12377 case ARM::WIN__CHKSTK:
12378 return EmitLowered__chkstk(
MI, BB);
12379 case ARM::WIN__DBZCHK:
12380 return EmitLowered__dbzchk(
MI, BB);
12396 if (!
Node->hasAnyUseOfValue(0)) {
12397 MI.getOperand(0).setIsDead(
true);
12399 if (!
Node->hasAnyUseOfValue(1)) {
12400 MI.getOperand(1).setIsDead(
true);
12404 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12405 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12406 : &ARM::GPRRegClass);
12413 if (
MI.getOpcode() == ARM::MEMCPY) {
12434 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12435 &&
"converted opcode should be the same except for cc_out"
12436 " (and, on Thumb1, pred)");
12444 if (Subtarget->isThumb1Only()) {
12445 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12446 MI.addOperand(
MI.getOperand(1));
12447 MI.removeOperand(1);
12451 for (
unsigned i =
MI.getNumOperands(); i--;) {
12453 if (
op.isReg() &&
op.isUse()) {
12456 MI.tieOperands(DefIdx, i);
12464 ccOutIdx =
MCID->getNumOperands() - 1;
12466 ccOutIdx =
MCID->getNumOperands() - 1;
12470 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12471 assert(!NewOpc &&
"Optional cc_out operand required");
12476 bool definesCPSR =
false;
12477 bool deadCPSR =
false;
12478 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12482 definesCPSR =
true;
12485 MI.removeOperand(i);
12489 if (!definesCPSR) {
12490 assert(!NewOpc &&
"Optional cc_out operand required");
12493 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12495 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12496 "expect uninitialized optional cc_out operand");
12498 if (!Subtarget->isThumb1Only())
12534 switch (
N->getOpcode()) {
12535 default:
return false;
12537 CC =
N->getOperand(0);
12559 EVT VT =
N->getValueType(0);
12560 CC =
N->getOperand(0);
12607 EVT VT =
N->getValueType(0);
12610 bool SwapSelectOps;
12612 NonConstantVal, DAG))
12618 OtherOp, NonConstantVal);
12624 CCOp, TrueVal, FalseVal);
12648 if (
N->getOpcode() ==
ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12663 if (!
N->getValueType(0).is64BitVector())
12671 EVT VT =
N->getValueType(0);
12710 EVT VT =
N->getValueType(0);
12716 Opcode = Intrinsic::arm_neon_vpaddls;
12718 Opcode = Intrinsic::arm_neon_vpaddlu;
12746 EVT VT =
N->getValueType(0);
12761 unsigned nextIndex = 0;
12812 Ops.push_back(Vec);
12829 return DAG.
getNode(ExtOp, dl, VT, tmp);
12860 if (SRA.getOpcode() !=
ISD::SRA) {
12867 if (Const->getZExtValue() != 31)
12872 if (SRA.getOperand(0) !=
Mul)
12876 SDLoc dl(AddcNode);
12877 unsigned Opcode = 0;
12883 Op0 =
Mul.getOperand(0);
12884 Op1 =
Mul.getOperand(1);
12887 Op0 =
Mul.getOperand(0);
12888 Op1 =
Mul.getOperand(1).getOperand(0);
12891 Op0 =
Mul.getOperand(0).getOperand(0);
12892 Op1 =
Mul.getOperand(1);
12895 Op0 =
Mul->getOperand(0).getOperand(0);
12896 Op1 =
Mul->getOperand(1).getOperand(0);
12905 SDValue HiMLALResult(SMLAL.getNode(), 1);
12906 SDValue LoMLALResult(SMLAL.getNode(), 0);
12912 SDValue resNode(AddcNode, 0);
12941 "Expect an ADDE or SUBE");
12945 "ADDE node has the wrong inputs");
12964 "Expect ADDC with two result values. First: i32");
12984 bool IsLeftOperandMUL =
false;
12989 IsLeftOperandMUL =
true;
13000 SDValue *LowAddSub =
nullptr;
13003 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
13006 if (IsLeftOperandMUL)
13007 HiAddSub = &AddeSubeOp1;
13009 HiAddSub = &AddeSubeOp0;
13014 if (AddcSubcOp0 == MULOp.
getValue(0)) {
13015 LoMul = &AddcSubcOp0;
13016 LowAddSub = &AddcSubcOp1;
13018 if (AddcSubcOp1 == MULOp.
getValue(0)) {
13019 LoMul = &AddcSubcOp1;
13020 LowAddSub = &AddcSubcOp0;
13028 if (AddcSubcNode == HiAddSub->getNode() ||
13044 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13049 Ops.push_back(*HiAddSub);
13058 return SDValue(AddeSubeNode, 0);
13065 Ops.push_back(*LowAddSub);
13066 Ops.push_back(*HiAddSub);
13079 return SDValue(AddeSubeNode, 0);
13091 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13100 SDNode *UmlalNode =
nullptr;
13139 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13144 SDNode* AddcNode =
N->getOperand(2).getNode();
13145 SDNode* AddeNode =
N->getOperand(3).getNode();
13153 {N->getOperand(0), N->getOperand(1),
13154 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13178 int32_t imm =
C->getSExtValue();
13179 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13184 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13199 int64_t imm =
C->getSExtValue();
13210 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13211 N->getOperand(0),
RHS,
N->getOperand(2));
13223 if (!Subtarget->hasMVEIntegerOps())
13236 SetCC =
N->getOperand(0);
13240 TrueVal =
N->getOperand(1);
13241 FalseVal =
N->getOperand(2);
13243 LHS =
N->getOperand(0);
13244 RHS =
N->getOperand(1);
13246 TrueVal =
N->getOperand(2);
13247 FalseVal =
N->getOperand(3);
13252 unsigned int Opcode = 0;
13253 if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMIN ||
13254 FalseVal->getOpcode() == ISD::VECREDUCE_UMIN) &&
13259 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMIN ||
13260 FalseVal->getOpcode() == ISD::VECREDUCE_SMIN) &&
13265 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMAX ||
13266 FalseVal->getOpcode() == ISD::VECREDUCE_UMAX) &&
13271 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMAX ||
13272 FalseVal->getOpcode() == ISD::VECREDUCE_SMAX) &&
13281 switch (TrueVal->getOpcode()) {
13282 case ISD::VECREDUCE_UMIN:
13283 case ISD::VECREDUCE_SMIN:
13284 case ISD::VECREDUCE_UMAX:
13285 case ISD::VECREDUCE_SMAX:
13300 if (TrueVal !=
LHS || FalseVal !=
RHS)
13303 EVT LeftType =
LHS->getValueType(0);
13304 EVT RightType =
RHS->getValueType(0);
13307 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13311 if (VectorScalarType != MVT::i32)
13319 if (VectorScalarType != MVT::i32)
13332 EVT VT =
N->getValueType(0);
13340 Shft =
N->getOperand(0);
13347 Cmp.getOperand(0) !=
N->getOperand(1) ||
13348 Cmp.getOperand(1) !=
N->getOperand(2))
13350 Shft =
N->getOperand(1);
13362 ScalarType = MVT::i8;
13365 case (1 << 15) - 1:
13366 ScalarType = MVT::i16;
13369 case (1ULL << 31) - 1:
13370 ScalarType = MVT::i32;
13401 unsigned LegalLanes = 128 / (ShftAmt + 1);
13425 for (
unsigned I = 0;
I < NumParts; ++
I) {
13442 if (!Subtarget->hasMVEIntegerOps())
13457 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13467 if (!Const || !Const->isOne())
13485 EVT VT =
N->getValueType(0);
13487 if (!Subtarget->hasMVEIntegerOps() ||
13516 Opc = Intrinsic::arm_mve_vctp64;
13519 Opc = Intrinsic::arm_mve_vctp32;
13522 Opc = Intrinsic::arm_mve_vctp16;
13525 Opc = Intrinsic::arm_mve_vctp8;
13579 EVT VT =
N->getValueType(0);
13585 switch (
Op.getOpcode()) {
13586 case ISD::VECREDUCE_ADD:
13610 unsigned N0RedOp = 0;
13617 unsigned N1RedOp = 0;
13631 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13633 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13640 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13664 if (!BaseLocDecomp0.getBase() ||
13665 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13666 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13668 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13670 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13680 if (IsBefore < 0) {
13683 }
else if (IsBefore > 0) {
13696 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13706 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13716 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13718 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13725 if (!Subtarget->hasMVEIntegerOps())
13731 EVT VT =
N->getValueType(0);
13736 if (VT != MVT::i64)
13747 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13767 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13816 "Expected shift op");
13818 SDValue ShiftLHS =
N->getOperand(0);
13832 if (Subtarget->isThumb1Only()) {
13843 if (Const->getAPIntValue().ult(256))
13846 Const->getAPIntValue().sgt(-256))
13862 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13863 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13864 "Expected XOR(SHIFT) pattern");
13869 if (XorC && ShiftC) {
13870 unsigned MaskIdx, MaskLen;
13871 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13872 unsigned ShiftAmt = ShiftC->getZExtValue();
13873 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13874 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13875 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13876 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13886 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13888 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13889 "Expected shift-shift mask");
13891 if (!Subtarget->isThumb1Only())
13901 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13903 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13908 if (!Subtarget->hasNEON()) {
13909 if (Subtarget->isThumb1Only())
13923 return Subtarget->hasVFP2Base();
13925 return Subtarget->hasVFP2Base();
13927 return Subtarget->hasFP64();
13930 return Subtarget->hasMVEFloatOps();
13959 if (ST->isThumb() && ST->isThumb1Only())
13963 for (
auto *U :
N->users()) {
13964 switch(U->getOpcode()) {
13982 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13983 U->getOperand(1).getOpcode() ==
ISD::SHL)
13993 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
14000 if (!C1ShlC2 || !C2)
14003 APInt C2Int = C2->getAPIntValue();
14004 APInt C1Int = C1ShlC2->getAPIntValue();
14006 if (C2Int.
uge(C2Width))
14012 if ((C1Int & Mask) != C1Int)
14019 auto LargeImm = [](
const APInt &Imm) {
14020 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
14021 return Imm.getBitWidth() - Zeros > 8;
14024 if (LargeImm(C1Int) || LargeImm(C2Int))
14036 SHL.dump();
N->dump());
14071 if (CSINC.getOpcode() !=
ARMISD::CSINC || !CSINC.hasOneUse())
14080 CSINC.getOperand(0)),
14081 CSINC.getOperand(1), CSINC.getOperand(2),
14082 CSINC.getOperand(3));
14101 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14143 if (!Subtarget->hasVMLxForwarding())
14162 EVT VT =
N->getValueType(0);
14173 EVT VT =
N->getValueType(0);
14174 if (VT != MVT::v2i64)
14185 return Op->getOperand(0);
14198 if (
And->getOpcode() == ISD::BITCAST)
14199 And =
And->getOperand(0);
14203 if (Mask->getOpcode() == ISD::BITCAST)
14204 Mask = Mask->getOperand(0);
14207 Mask.getValueType() != MVT::v4i32)
14213 return And->getOperand(0);
14218 if (
SDValue Op0 = IsSignExt(N0)) {
14219 if (
SDValue Op1 = IsSignExt(N1)) {
14225 if (
SDValue Op0 = IsZeroExt(N0)) {
14226 if (
SDValue Op1 = IsZeroExt(N1)) {
14241 EVT VT =
N->getValueType(0);
14242 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14253 if (VT != MVT::i32)
14260 int64_t MulAmt =
C->getSExtValue();
14263 ShiftAmt = ShiftAmt & (32 - 1);
14268 MulAmt >>= ShiftAmt;
14329 if (
N->getValueType(0) != MVT::i32)
14338 if (C1 == 255 || C1 == 65535)
14341 SDNode *N0 =
N->getOperand(0).getNode();
14355 if (!C2 || C2 >= 32)
14399 if (Trailing == C2 && C2 + C3 < 32) {
14412 if (Leading == C2 && C2 + C3 < 32) {
14440 EVT VT =
N->getValueType(0);
14444 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14447 APInt SplatBits, SplatUndef;
14448 unsigned SplatBitSize;
14450 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14451 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14452 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14453 SplatBitSize == 64) {
14487 if (!Subtarget->hasV6Ops() ||
14488 (Subtarget->isThumb() &&
14489 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14492 SDValue SRL = OR->getOperand(0);
14493 SDValue SHL = OR->getOperand(1);
14496 SRL = OR->getOperand(1);
14497 SHL = OR->getOperand(0);
14504 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14508 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14509 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14510 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14529 unsigned Opcode = 0;
14530 if (
isS16(OpS16, DAG))
14548 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14551 EVT VT =
N->getValueType(0);
14566 if (VT != MVT::i32)
14579 if (Mask == 0xffff)
14586 if ((Val & ~Mask) != Val)
14611 (Mask == ~Mask2)) {
14614 if (Subtarget->hasDSP() &&
14615 (Mask == 0xffff || Mask == 0xffff0000))
14628 (~Mask == Mask2)) {
14631 if (Subtarget->hasDSP() &&
14632 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14698 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14705 EVT VT =
N->getValueType(0);
14710 auto IsFreelyInvertable = [&](
SDValue V) {
14717 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14733 EVT VT =
N->getValueType(0);
14739 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14740 VT == MVT::v8i1 || VT == MVT::v16i1))
14743 APInt SplatBits, SplatUndef;
14744 unsigned SplatBitSize;
14746 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14747 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14748 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14749 SplatBitSize == 64) {
14785 unsigned SplatBitSize;
14788 APInt SplatBits0, SplatBits1;
14792 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14793 HasAnyUndefs) && !HasAnyUndefs) {
14794 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14795 HasAnyUndefs) && !HasAnyUndefs) {
14800 SplatBits0 == ~SplatBits1) {
14830 EVT VT =
N->getValueType(0);
14845 if (Subtarget->hasMVEIntegerOps()) {
14876 ToMask =
~N->getConstantOperandAPInt(2);
14896 unsigned LastActiveBitInA =
A.countr_zero();
14897 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14898 return LastActiveBitInA - 1 == FirstActiveBitInB;
14903 APInt ToMask, FromMask;
14911 APInt NewToMask, NewFromMask;
14913 if (NewFrom != From)
14917 if ((NewToMask & ToMask).getBoolValue())
14942 unsigned InvMask =
N->getConstantOperandVal(2);
14946 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14947 "undefined behavior");
14948 unsigned Mask = (1u << Width) - 1;
14950 if ((Mask & (~Mask2)) == 0)
14952 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14959 APInt ToMask1, FromMask1;
14962 APInt ToMask2, FromMask2;
14968 APInt NewFromMask = FromMask1 | FromMask2;
14969 APInt NewToMask = ToMask1 | ToMask2;
14971 EVT VT =
N->getValueType(0);
14974 if (NewFromMask[0] == 0)
14986 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14987 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14989 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14993 EVT VT =
N->getValueType(0);
14996 N->getOperand(1),
N->getOperand(2));
15010 SDValue CSInc = Cmp->getOperand(0);
15060 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15061 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15064 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15066 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15079 SDValue InDouble =
N->getOperand(0);
15094 SDValue BasePtr = LD->getBasePtr();
15096 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15097 LD->getAlign(), LD->getMemOperand()->getFlags());
15103 LD->getPointerInfo().getWithOffset(4),
15105 LD->getMemOperand()->getFlags());
15121 bool BVSwap = BV.
getOpcode() == ISD::BITCAST;
15126 BVSwap = BV.
getOpcode() == ISD::BITCAST;
15138 if (!Subtarget->
isLittle() && BVSwap)
15156 if (!Subtarget->
isLittle() && BVSwap)
15199 if (Op0->
getOpcode() == ISD::BITCAST) {
15201 if (Copy.getValueType() == MVT::f32 &&
15203 bool HasGlue = Copy->getNumOperands() == 3;
15204 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15205 HasGlue ? Copy->getOperand(2) :
SDValue()};
15206 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15225 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15226 LN0->getMemoryVT() == MVT::i16) {
15229 LN0->getBasePtr(), LN0->getMemOperand());
15247 EVT VT =
N->getValueType(0);
15281 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15282 for (
unsigned i = 0; i < NumElts; ++i) {
15283 SDNode *Elt =
N->getOperand(i).getNode();
15300 if (
N->getNumOperands() == 2)
15306 EVT VT =
N->getValueType(0);
15312 for (
unsigned i = 0; i < NumElts; ++i) {
15313 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(i));
15320 return DAG.
getNode(ISD::BITCAST, dl, VT, BV);
15338 EVT VT =
N->getValueType(0);
15346 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15350 if (
Use->getOpcode() != ISD::BITCAST ||
15351 Use->getValueType(0).isFloatingPoint())
15359 unsigned NumOfBitCastedElts = 0;
15361 unsigned NumOfRelevantElts = NumElts;
15362 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15364 if (Elt->
getOpcode() == ISD::BITCAST) {
15367 ++NumOfBitCastedElts;
15371 --NumOfRelevantElts;
15375 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15393 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15397 if (V.getOpcode() == ISD::BITCAST &&
15398 V->getOperand(0).getValueType() == MVT::i32)
15400 V = V.getOperand(0);
15409 Vec = DAG.
getNode(ISD::BITCAST, dl, VT, Vec);
15417 EVT VT =
N->getValueType(0);
15424 if (
Op->getOperand(0).getValueType() == VT)
15425 return Op->getOperand(0);
15440 if (
Op.getValueType() == MVT::i32) {
15451 EVT VT =
N->getValueType(0);
15456 if (ST->isLittle())
15457 return DAG.
getNode(ISD::BITCAST, dl, VT,
Op);
15460 if (
Op.getValueType() == VT)
15469 if (
Op->getOperand(0).getValueType() == VT)
15470 return Op->getOperand(0);
15479 if (!Subtarget->hasMVEIntegerOps())
15482 EVT VT =
N->getValueType(0);
15513 EVT VT =
N->getValueType(0);
15514 SDNode *Elt =
N->getOperand(1).getNode();
15523 SDValue Vec = DAG.
getNode(ISD::BITCAST, dl, FloatVT,
N->getOperand(0));
15524 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(1));
15529 Vec, V,
N->getOperand(2));
15530 return DAG.
getNode(ISD::BITCAST, dl, VT, InsElt);
15539 EVT VT =
N->getValueType(0);
15547 if (Ext.getOpcode() == ISD::BITCAST &&
15548 Ext.getOperand(0).getValueType() == MVT::f32)
15549 Ext = Ext.getOperand(0);
15552 Ext.getConstantOperandVal(1) % 2 != 0)
15554 if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() ==
ISD::SINT_TO_FP ||
15558 SDValue Op0 = Ext.getOperand(0);
15561 unsigned Lane = Ext.getConstantOperandVal(1);
15567 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15568 isa<ConstantSDNode>(V->getOperand(1)) &&
15569 V->getConstantOperandVal(1) == Lane + 1 &&
15570 V->getOperand(0).getResNo() == ResNo;
15572 if (OtherIt == Op0->
users().
end())
15577 SDValue OtherExt(*OtherIt, 0);
15590 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15602 EVT VT =
N->getValueType(0);
15608 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15610 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15612 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15615 while (
X.getValueType() != VT &&
X->getOpcode() == ISD::BITCAST)
15616 X =
X->getOperand(0);
15617 if (
X.getValueType() == VT)
15625 return Op0.
getOperand(
N->getConstantOperandVal(1));
15635 unsigned Offset =
N->getConstantOperandVal(1);
15647 unsigned Idx =
N->getConstantOperandVal(1);
15661 EVT VT =
N->getValueType(0);
15666 Op.getOperand(0).getValueType().getScalarType())
15676 SDValue SubVec =
N->getOperand(1);
15677 uint64_t IdxVal =
N->getConstantOperandVal(2);
15688 if (IdxVal == 0 && Vec.
isUndef())
15694 (IdxVal != 0 && IdxVal != NumSubElts))
15767 EVT VT =
N->getValueType(0);
15778 unsigned HalfElts = NumElts/2;
15780 for (
unsigned n = 0; n < NumElts; ++n) {
15783 if (MaskElt < (
int)HalfElts)
15785 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15786 NewElt = HalfElts + MaskElt - NumElts;
15829 bool SimpleConstIncOnly,
15837 bool isLoadOp =
true;
15838 bool isLaneOp =
false;
15841 bool hasAlignment =
true;
15842 unsigned NewOpc = 0;
15843 unsigned NumVecs = 0;
15844 if (
Target.isIntrinsic) {
15845 unsigned IntNo =
N->getConstantOperandVal(1);
15849 case Intrinsic::arm_neon_vld1:
15853 case Intrinsic::arm_neon_vld2:
15857 case Intrinsic::arm_neon_vld3:
15861 case Intrinsic::arm_neon_vld4:
15865 case Intrinsic::arm_neon_vld1x2:
15868 hasAlignment =
false;
15870 case Intrinsic::arm_neon_vld1x3:
15873 hasAlignment =
false;
15875 case Intrinsic::arm_neon_vld1x4:
15878 hasAlignment =
false;
15880 case Intrinsic::arm_neon_vld2dup:
15884 case Intrinsic::arm_neon_vld3dup:
15888 case Intrinsic::arm_neon_vld4dup:
15892 case Intrinsic::arm_neon_vld2lane:
15897 case Intrinsic::arm_neon_vld3lane:
15902 case Intrinsic::arm_neon_vld4lane:
15907 case Intrinsic::arm_neon_vst1:
15912 case Intrinsic::arm_neon_vst2:
15917 case Intrinsic::arm_neon_vst3:
15922 case Intrinsic::arm_neon_vst4:
15927 case Intrinsic::arm_neon_vst2lane:
15933 case Intrinsic::arm_neon_vst3lane:
15939 case Intrinsic::arm_neon_vst4lane:
15945 case Intrinsic::arm_neon_vst1x2:
15949 hasAlignment =
false;
15951 case Intrinsic::arm_neon_vst1x3:
15955 hasAlignment =
false;
15957 case Intrinsic::arm_neon_vst1x4:
15961 hasAlignment =
false;
15966 switch (
N->getOpcode()) {
16002 VecTy =
N->getValueType(0);
16003 }
else if (
Target.isIntrinsic) {
16004 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16007 "Node has to be a load, a store, or an intrinsic!");
16008 VecTy =
N->getOperand(1).getValueType();
16016 if (isLaneOp || isVLDDUPOp)
16019 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16025 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16034 EVT AlignedVecTy = VecTy;
16054 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16055 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16066 Alignment =
Align(1);
16072 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16074 for (n = 0; n < NumResultVecs; ++n)
16075 Tys[n] = AlignedVecTy;
16076 Tys[n++] = MVT::i32;
16077 Tys[n] = MVT::Other;
16082 Ops.push_back(
N->getOperand(0));
16083 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16088 Ops.push_back(StN->getValue());
16092 unsigned LastOperand =
16093 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16094 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16095 Ops.push_back(
N->getOperand(i));
16103 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::STORE) {
16105 StVal = DAG.
getNode(ISD::BITCAST, dl, AlignedVecTy, StVal);
16114 for (
unsigned i = 0; i < NumResultVecs; ++i)
16119 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::LOAD) {
16120 SDValue &LdVal = NewResults[0];
16121 LdVal = DAG.
getNode(ISD::BITCAST, dl, VecTy, LdVal);
16156 switch (
N->getOpcode()) {
16160 *
Ptr =
N->getOperand(0);
16161 *CInc =
N->getOperand(1);
16168 *
Ptr =
N->getOperand(1);
16169 *CInc =
N->getOperand(2);
16188 const bool isStore =
N->getOpcode() == ISD::STORE;
16196 SDValue Addr =
N->getOperand(AddrOpIdx);
16207 unsigned ConstInc =
16212 if (BaseUpdates.
size() >= MaxBaseUpdates)
16232 unsigned UserOffset =
16235 if (!UserOffset || UserOffset <=
Offset)
16238 unsigned NewConstInc = UserOffset -
Offset;
16241 if (BaseUpdates.
size() >= MaxBaseUpdates)
16248 unsigned NumValidUpd = BaseUpdates.
size();
16249 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16260 return LHS.ConstInc <
RHS.ConstInc;
16289 unsigned IntNo =
N->getConstantOperandVal(1);
16290 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16292 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16315 bool isLoadOp =
true;
16316 unsigned NewOpc = 0;
16317 unsigned NumVecs = 0;
16321 case Intrinsic::arm_mve_vld2q:
16325 case Intrinsic::arm_mve_vld4q:
16329 case Intrinsic::arm_mve_vst2q:
16334 case Intrinsic::arm_mve_vst4q:
16344 VecTy =
N->getValueType(0);
16346 VecTy =
N->getOperand(3).getValueType();
16360 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16362 for (n = 0; n < NumResultVecs; ++n)
16364 Tys[n++] = MVT::i32;
16365 Tys[n] = MVT::Other;
16370 Ops.push_back(
N->getOperand(0));
16371 Ops.push_back(
N->getOperand(2));
16372 Ops.push_back(Inc);
16374 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16375 Ops.push_back(
N->getOperand(i));
16382 for (
unsigned i = 0; i < NumResultVecs; ++i)
16401 EVT VT =
N->getValueType(0);
16407 SDNode *VLD =
N->getOperand(0).getNode();
16410 unsigned NumVecs = 0;
16411 unsigned NewOpc = 0;
16413 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16416 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16419 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16431 if (
Use.getResNo() == NumVecs)
16435 VLDLaneNo !=
User->getConstantOperandVal(1))
16442 for (n = 0; n < NumVecs; ++n)
16444 Tys[n] = MVT::Other;
16454 unsigned ResNo =
Use.getResNo();
16456 if (ResNo == NumVecs)
16463 std::vector<SDValue> VLDDupResults;
16464 for (
unsigned n = 0; n < NumVecs; ++n)
16478 EVT VT =
N->getValueType(0);
16481 if (Subtarget->hasMVEIntegerOps()) {
16485 ExtractVT = MVT::i32;
16487 N->getOperand(0),
N->getOperand(1));
16498 while (
Op.getOpcode() == ISD::BITCAST)
16499 Op =
Op.getOperand(0);
16504 unsigned EltSize =
Op.getScalarValueSizeInBits();
16506 unsigned Imm =
Op.getConstantOperandVal(0);
16522 if (Subtarget->hasMVEIntegerOps()) {
16525 if (
Op.getValueType() == MVT::f32)
16527 DAG.
getNode(ISD::BITCAST, dl, MVT::i32,
Op));
16528 else if (
Op.getValueType() == MVT::f16)
16533 if (!Subtarget->hasNEON())
16540 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16541 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16542 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16547 LD->getMemoryVT(), LD->getMemOperand());
16558 EVT VT =
N->getValueType(0);
16580 assert(StVT != VT &&
"Cannot truncate to the same type");
16590 if (0 != (NumElems * FromEltSz) % ToEltSz)
16593 unsigned SizeRatio = FromEltSz / ToEltSz;
16598 NumElems * SizeRatio);
16604 for (
unsigned i = 0; i < NumElems; ++i)
16618 MVT StoreType = MVT::i8;
16620 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16640 for (
unsigned I = 0;
I <
E;
I++) {
16671 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16674 unsigned NumElements = 4;
16691 unsigned Off0 = Rev ? NumElts : 0;
16692 unsigned Off1 = Rev ? 0 : NumElts;
16694 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16695 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16697 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16705 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16725 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16740 NewToVT, Alignment, MMOFlags, AAInfo);
16773 unsigned NewOffset =
16781 NewToVT, Alignment, MMOFlags, AAInfo);
16803 {Extract.getOperand(0), Extract.getOperand(1)});
16834 if (Subtarget->hasNEON())
16838 if (Subtarget->hasMVEFloatOps())
16842 if (Subtarget->hasMVEIntegerOps()) {
16917 if (!Subtarget->hasNEON())
16921 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16929 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16931 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16932 uint32_t IntBits = IntTy.getSizeInBits();
16933 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16934 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16945 if (
C == -1 ||
C == 0 ||
C > 32)
16950 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16951 Intrinsic::arm_neon_vcvtfp2fxu;
16954 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16957 if (IntBits < FloatBits)
16965 if (!Subtarget->hasMVEFloatOps())
16973 EVT VT =
N->getValueType(0);
16978 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16979 if (
Op.getOpcode() != ISD::BITCAST ||
16982 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16983 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16985 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16998 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17009 EVT VT =
N->getValueType(0);
17012 if (!
N->getFlags().hasAllowReassociation())
17019 unsigned Opc =
A.getConstantOperandVal(0);
17020 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17025 A.getOperand(3),
A.getOperand(4));
17057 if (!Subtarget->hasNEON())
17061 unsigned OpOpcode =
Op.getNode()->getOpcode();
17062 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17066 SDValue ConstVec =
N->getOperand(1);
17070 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17072 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17073 uint32_t IntBits = IntTy.getSizeInBits();
17074 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17075 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17095 int32_t
C = IntVal.exactLogBase2();
17096 if (
C == -1 ||
C == 0 ||
C > 32)
17102 if (IntBits < FloatBits)
17104 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17106 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17107 : Intrinsic::arm_neon_vcvtfxu2fp;
17115 if (!ST->hasMVEIntegerOps())
17118 assert(
N->getOpcode() == ISD::VECREDUCE_ADD);
17119 EVT ResVT =
N->getValueType(0);
17147 EVT AVT =
A.getValueType();
17153 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17154 EVT AVT =
A.getValueType();
17162 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17163 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17166 if (ExtTypeMatches(
A, ExtTypes))
17167 return ExtendIfNeeded(
A, ExtendCode);
17170 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17177 if (Ext->getOpcode() != ExtendCode)
17180 if (ExtTypeMatches(
A, ExtTypes))
17181 return ExtendIfNeeded(
A, ExtendCode);
17184 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17194 if (ResVT != RetTy)
17197 if (
Mul->getOpcode() == ExtendCode &&
17198 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17200 Mul =
Mul->getOperand(0);
17209 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17210 A = ExtendIfNeeded(
A, ExtendCode);
17211 B = ExtendIfNeeded(
B, ExtendCode);
17216 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17229 if (
Mul->getOpcode() == ExtendCode &&
17230 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17232 Mul =
Mul->getOperand(0);
17241 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17242 A = ExtendIfNeeded(
A, ExtendCode);
17243 B = ExtendIfNeeded(
B, ExtendCode);
17254 EVT VT =
Ops[0].getValueType();
17255 if (VT == MVT::v16i8) {
17257 "Unexpected illegal long reduction opcode");
17286 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17289 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17353 Op =
Op->getOperand(1);
17355 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17357 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17363 return DAG.
getNode(ISD::VECREDUCE_ADD, dl, ResVT, Ext);
17374 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17376 if (!Shuf || !Shuf->getOperand(1).isUndef())
17381 APInt SetElts(Mask.size(), 0);
17382 for (
int E : Mask) {
17390 if (
N->getNumOperands() != VecOp + 1) {
17392 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17398 if (
Op.getValueType().isVector())
17399 Ops.push_back(
Op.getOperand(0));
17410 unsigned IsTop =
N->getConstantOperandVal(2);
17417 if (Op0->
isUndef() && !IsTop)
17431 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17433 APInt Op0DemandedElts =
17434 IsTop ? Op1DemandedElts
17449 unsigned IsTop =
N->getConstantOperandVal(2);
17451 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17452 APInt Op0DemandedElts =
17464 EVT VT =
N->getValueType(0);
17471 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17472 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17476 LHS.getOperand(0),
RHS.getOperand(0));
17491 int ShiftAmt =
C->getSExtValue();
17492 if (ShiftAmt == 0) {
17498 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17499 unsigned NewOpcode =
17515 unsigned IntNo =
N->getConstantOperandVal(0);
17526 case Intrinsic::arm_neon_vshifts:
17527 case Intrinsic::arm_neon_vshiftu:
17528 case Intrinsic::arm_neon_vrshifts:
17529 case Intrinsic::arm_neon_vrshiftu:
17530 case Intrinsic::arm_neon_vrshiftn:
17531 case Intrinsic::arm_neon_vqshifts:
17532 case Intrinsic::arm_neon_vqshiftu:
17533 case Intrinsic::arm_neon_vqshiftsu:
17534 case Intrinsic::arm_neon_vqshiftns:
17535 case Intrinsic::arm_neon_vqshiftnu:
17536 case Intrinsic::arm_neon_vqshiftnsu:
17537 case Intrinsic::arm_neon_vqrshiftns:
17538 case Intrinsic::arm_neon_vqrshiftnu:
17539 case Intrinsic::arm_neon_vqrshiftnsu: {
17540 EVT VT =
N->getOperand(1).getValueType();
17542 unsigned VShiftOpc = 0;
17545 case Intrinsic::arm_neon_vshifts:
17546 case Intrinsic::arm_neon_vshiftu:
17551 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17558 case Intrinsic::arm_neon_vrshifts:
17559 case Intrinsic::arm_neon_vrshiftu:
17564 case Intrinsic::arm_neon_vqshifts:
17565 case Intrinsic::arm_neon_vqshiftu:
17570 case Intrinsic::arm_neon_vqshiftsu:
17575 case Intrinsic::arm_neon_vrshiftn:
17576 case Intrinsic::arm_neon_vqshiftns:
17577 case Intrinsic::arm_neon_vqshiftnu:
17578 case Intrinsic::arm_neon_vqshiftnsu:
17579 case Intrinsic::arm_neon_vqrshiftns:
17580 case Intrinsic::arm_neon_vqrshiftnu:
17581 case Intrinsic::arm_neon_vqrshiftnsu:
17593 case Intrinsic::arm_neon_vshifts:
17594 case Intrinsic::arm_neon_vshiftu:
17597 case Intrinsic::arm_neon_vrshifts:
17600 case Intrinsic::arm_neon_vrshiftu:
17603 case Intrinsic::arm_neon_vrshiftn:
17606 case Intrinsic::arm_neon_vqshifts:
17609 case Intrinsic::arm_neon_vqshiftu:
17612 case Intrinsic::arm_neon_vqshiftsu:
17615 case Intrinsic::arm_neon_vqshiftns:
17618 case Intrinsic::arm_neon_vqshiftnu:
17621 case Intrinsic::arm_neon_vqshiftnsu:
17624 case Intrinsic::arm_neon_vqrshiftns:
17627 case Intrinsic::arm_neon_vqrshiftnu:
17630 case Intrinsic::arm_neon_vqrshiftnsu:
17636 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17637 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17640 case Intrinsic::arm_neon_vshiftins: {
17641 EVT VT =
N->getOperand(1).getValueType();
17643 unsigned VShiftOpc = 0;
17647 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17654 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17655 N->getOperand(1),
N->getOperand(2),
17659 case Intrinsic::arm_neon_vqrshifts:
17660 case Intrinsic::arm_neon_vqrshiftu:
17664 case Intrinsic::arm_neon_vbsl: {
17667 N->getOperand(2),
N->getOperand(3));
17669 case Intrinsic::arm_mve_vqdmlah:
17670 case Intrinsic::arm_mve_vqdmlash:
17671 case Intrinsic::arm_mve_vqrdmlah:
17672 case Intrinsic::arm_mve_vqrdmlash:
17673 case Intrinsic::arm_mve_vmla_n_predicated:
17674 case Intrinsic::arm_mve_vmlas_n_predicated:
17675 case Intrinsic::arm_mve_vqdmlah_predicated:
17676 case Intrinsic::arm_mve_vqdmlash_predicated:
17677 case Intrinsic::arm_mve_vqrdmlah_predicated:
17678 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17683 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17690 case Intrinsic::arm_mve_minv:
17691 case Intrinsic::arm_mve_maxv:
17692 case Intrinsic::arm_mve_minav:
17693 case Intrinsic::arm_mve_maxav:
17694 case Intrinsic::arm_mve_minv_predicated:
17695 case Intrinsic::arm_mve_maxv_predicated:
17696 case Intrinsic::arm_mve_minav_predicated:
17697 case Intrinsic::arm_mve_maxav_predicated: {
17700 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17707 case Intrinsic::arm_mve_addv: {
17710 bool Unsigned =
N->getConstantOperandVal(2);
17715 case Intrinsic::arm_mve_addlv:
17716 case Intrinsic::arm_mve_addlv_predicated: {
17719 bool Unsigned =
N->getConstantOperandVal(2);
17720 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17725 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17727 Ops.push_back(
N->getOperand(i));
17748 EVT VT =
N->getValueType(0);
17750 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17751 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17752 N->getOperand(0)->hasOneUse()) {
17769 if (AndMask == 255 || AndMask == 65535)
17773 if (MaskedBits > ShiftAmt) {
17788 if (ST->hasMVEIntegerOps())
17793 switch (
N->getOpcode()) {
17806 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17807 unsigned VShiftOpc =
17810 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17826 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17829 EVT FromVT = LD->getValueType(0);
17830 EVT ToVT =
N->getValueType(0);
17837 unsigned NumElements = 0;
17838 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17840 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17842 if (NumElements == 0 ||
17852 SDValue BasePtr = LD->getBasePtr();
17853 Align Alignment = LD->getBaseAlign();
17874 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17875 Alignment, MMOFlags, AAInfo);
17881 if (FromEltVT == MVT::f16) {
17884 for (
unsigned i = 0; i < Loads.
size(); i++) {
17910 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17914 EVT VT =
N->getValueType(0);
17918 if (VT == MVT::i32 &&
17919 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17924 switch (
N->getOpcode()) {
17938 if (ST->hasMVEIntegerOps())
17947 if (ST->hasMVEFloatOps())
17958 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17962 EVT VT =
Op.getValueType();
17965 if (VT != MVT::i32 ||
17978 APInt MaxC = Max.getConstantOperandAPInt(1);
17981 !(MinC + 1).isPowerOf2())
17999 EVT VT =
N->getValueType(0);
18002 if (VT == MVT::i32)
18005 if (!ST->hasMVEIntegerOps())
18011 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18014 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18022 if (VT == MVT::v4i32)
18023 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18025 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18032 MaxC != ~SaturateC)
18037 if (IsSignedSaturate(
N, N0.
getNode())) {
18040 if (VT == MVT::v4i32) {
18041 HalfVT = MVT::v8i16;
18042 ExtVT = MVT::v4i16;
18044 HalfVT = MVT::v16i8;
18059 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18065 if (VT == MVT::v4i32)
18066 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18068 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18077 if (IsUnsignedSaturate(
N)) {
18081 if (VT == MVT::v4i32) {
18082 HalfVT = MVT::v8i16;
18083 ExtConst = 0x0000FFFF;
18085 HalfVT = MVT::v16i8;
18107 const APInt *CV = &
C->getAPIntValue();
18125 SDValue Op0 = CMOV->getOperand(0);
18126 SDValue Op1 = CMOV->getOperand(1);
18127 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
18128 SDValue CmpZ = CMOV->getOperand(3);
18164 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18171 if ((OrCI & Known.
Zero) != OrCI)
18177 EVT VT =
X.getValueType();
18178 unsigned BitInX = AndC->
logBase2();
18186 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18187 BitInY < NumActiveBits; ++BitInY) {
18188 if (OrCI[BitInY] == 0)
18191 Mask.setBit(BitInY);
18208 switch (
N->getOpcode()) {
18223 if (Const->isZero())
18225 else if (Const->isOne())
18233 unsigned IntOp =
N.getConstantOperandVal(1);
18234 if (IntOp != Intrinsic::test_start_loop_iterations &&
18235 IntOp != Intrinsic::loop_decrement_reg)
18261 bool Negate =
false;
18265 if (
N->getOpcode() == ISD::BRCOND) {
18267 Cond =
N->getOperand(1);
18268 Dest =
N->getOperand(2);
18270 assert(
N->getOpcode() == ISD::BR_CC &&
"Expected BRCOND or BR_CC!");
18272 Cond =
N->getOperand(2);
18273 Dest =
N->getOperand(4);
18275 if (!Const->isOne() && !Const->isZero())
18277 Imm = Const->getZExtValue();
18305 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18306 "unsupported condition");
18311 unsigned IntOp =
Int->getConstantOperandVal(1);
18312 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() == ISD::BR) &&
18313 "expected single br user");
18314 SDNode *Br = *
N->user_begin();
18324 if (IntOp == Intrinsic::test_start_loop_iterations) {
18328 if (IsTrueIfZero(CC, Imm)) {
18334 UpdateUncondBr(Br, Dest, DAG);
18336 SDValue Ops[] = {Chain, Setup, OtherTarget};
18349 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18353 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18357 if (
Target == OtherTarget)
18358 UpdateUncondBr(Br, Dest, DAG);
18378 SDValue LHS = Cmp.getOperand(0);
18379 SDValue RHS = Cmp.getOperand(1);
18389 LHS->getOperand(0)->hasOneUse() &&
18409 EVT VT =
N->getValueType(0);
18411 SDValue LHS = Cmp.getOperand(0);
18412 SDValue RHS = Cmp.getOperand(1);
18413 SDValue FalseVal =
N->getOperand(0);
18414 SDValue TrueVal =
N->getOperand(1);
18419 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18443 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18445 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18457 LHS->getOperand(2), LHS->getOperand(3));
18467 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18471 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18473 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18482 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18547 const APInt *TrueConst;
18548 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18549 ((FalseVal.getOpcode() ==
ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18550 FalseVal.getOperand(1) == RHS) ||
18554 unsigned ShiftAmount = TrueConst->
logBase2();
18569 if (Known.
Zero == 0xfffffffe)
18572 else if (Known.
Zero == 0xffffff00)
18575 else if (Known.
Zero == 0xffff0000)
18588 EVT DstVT =
N->getValueType(0);
18591 if (ST->hasMVEIntegerOps() && Src.getOpcode() ==
ARMISD::VDUP) {
18592 EVT SrcVT = Src.getValueType();
18600 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18601 Src.getValueType().getScalarSizeInBits())
18602 Src = Src.getOperand(0);
18606 EVT SrcVT = Src.getValueType();
18626 EVT VT =
N->getValueType(0);
18634 if (
N->getNumOperands() == 2 &&
18638 N->getOperand(0).getOperand(1),
18639 N->getOperand(1).getOperand(0),
18640 N->getOperand(1).getOperand(1));
18643 if (
N->getNumOperands() == 2 &&
18649 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18650 S0->getOperand(1) ==
S1->getOperand(1)) {
18653 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18673 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18674 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18675 (Op.getOpcode() == ISD::BITCAST &&
18676 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18679 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18681 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18699 int NumIns =
N->getNumOperands();
18700 assert((NumIns == 2 || NumIns == 4) &&
18701 "Expected 2 or 4 inputs to an MVETrunc");
18703 if (
N->getNumOperands() == 4)
18707 for (
int I = 0;
I < NumIns;
I++) {
18709 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18729 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18732 EVT FromVT = LD->getMemoryVT();
18733 EVT ToVT =
N->getValueType(0);
18740 unsigned NumElements = 0;
18741 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18743 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18745 assert(NumElements != 0);
18751 LD->getExtensionType() != NewExtType)
18758 SDValue BasePtr = LD->getBasePtr();
18759 Align Alignment = LD->getBaseAlign();
18778 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18779 Alignment, MMOFlags, AAInfo);
18795 EVT VT =
N->getValueType(0);
18797 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18798 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18800 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18802 auto Extend = [&](
SDValue V) {
18812 SDValue Ext = Extend(
N->getOperand(0));
18820 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18825 auto CheckInregMask = [&](
int Start,
int Offset) {
18827 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18833 if (CheckInregMask(0, 0))
18835 else if (CheckInregMask(0, 1))
18836 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18837 else if (CheckInregMask(0, Mask.size()))
18839 else if (CheckInregMask(0, Mask.size() + 1))
18840 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18845 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18849 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18856 if (
N->getOperand(0)->getOpcode() == ISD::LOAD)
18867 int NumOuts =
N->getNumValues();
18868 assert((NumOuts == 2 || NumOuts == 4) &&
18869 "Expected 2 or 4 outputs to an MVEEXT");
18870 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18872 if (
N->getNumOperands() == 4)
18878 StackPtr, MPI,
Align(4));
18881 for (
int I = 0;
I < NumOuts;
I++) {
18883 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18884 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18889 VT, Chain,
Ptr, MPI, LoadVT,
Align(4));
18898 switch (
N->getOpcode()) {
18949 case ISD::FP_EXTEND:
18988 case ISD::VECREDUCE_ADD:
19015 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19022 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19033 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19041 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19043 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19051 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19053 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19061 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19072 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19080 if (
N->getOperand(1) ==
N->getOperand(2))
19081 return N->getOperand(1);
19085 switch (
N->getConstantOperandVal(1)) {
19086 case Intrinsic::arm_neon_vld1:
19087 case Intrinsic::arm_neon_vld1x2:
19088 case Intrinsic::arm_neon_vld1x3:
19089 case Intrinsic::arm_neon_vld1x4:
19090 case Intrinsic::arm_neon_vld2:
19091 case Intrinsic::arm_neon_vld3:
19092 case Intrinsic::arm_neon_vld4:
19093 case Intrinsic::arm_neon_vld2lane:
19094 case Intrinsic::arm_neon_vld3lane:
19095 case Intrinsic::arm_neon_vld4lane:
19096 case Intrinsic::arm_neon_vld2dup:
19097 case Intrinsic::arm_neon_vld3dup:
19098 case Intrinsic::arm_neon_vld4dup:
19099 case Intrinsic::arm_neon_vst1:
19100 case Intrinsic::arm_neon_vst1x2:
19101 case Intrinsic::arm_neon_vst1x3:
19102 case Intrinsic::arm_neon_vst1x4:
19103 case Intrinsic::arm_neon_vst2:
19104 case Intrinsic::arm_neon_vst3:
19105 case Intrinsic::arm_neon_vst4:
19106 case Intrinsic::arm_neon_vst2lane:
19107 case Intrinsic::arm_neon_vst3lane:
19108 case Intrinsic::arm_neon_vst4lane:
19110 case Intrinsic::arm_mve_vld2q:
19111 case Intrinsic::arm_mve_vld4q:
19112 case Intrinsic::arm_mve_vst2q:
19113 case Intrinsic::arm_mve_vst4q:
19124 return (VT == MVT::f32) && (
Opc == ISD::LOAD ||
Opc == ISD::STORE);
19130 unsigned *
Fast)
const {
19136 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19139 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19141 if (AllowsUnaligned) {
19143 *
Fast = Subtarget->hasV7Ops();
19148 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19152 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19159 if (!Subtarget->hasMVEIntegerOps())
19163 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19164 Ty == MVT::v2i1)) {
19172 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19188 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19189 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19190 Ty == MVT::v2f64) {
19201 const AttributeList &FuncAttributes)
const {
19203 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19204 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19206 if (
Op.size() >= 16 &&
19212 }
else if (
Op.size() >= 8 &&
19229 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19231 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19233 return (SrcBits == 64 && DestBits == 32);
19242 return (SrcBits == 64 && DestBits == 32);
19278 return Subtarget->hasFullFP16();
19285 if (!Subtarget->hasMVEIntegerOps())
19304 if (Ld->isExpandingLoad())
19308 if (Subtarget->hasMVEIntegerOps())
19353bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19355 if (Subtarget->useSoftFloat())
19364 return Subtarget->hasMVEFloatOps();
19382 unsigned Scale = 1;
19399 if ((V & (Scale - 1)) != 0)
19408 if (VT.
isVector() && Subtarget->hasNEON())
19411 !Subtarget->hasMVEFloatOps())
19414 bool IsNeg =
false;
19420 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19423 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19439 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19445 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19475 default:
return false;
19494 int Scale = AM.
Scale;
19499 default:
return false;
19507 Scale = Scale & ~1;
19508 return Scale == 2 || Scale == 4 || Scale == 8;
19525 if (Scale & 1)
return false;
19532 const int Scale = AM.
Scale;
19542 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19558 switch (AM.
Scale) {
19569 if (Subtarget->isThumb1Only())
19572 if (Subtarget->isThumb2())
19575 int Scale = AM.
Scale;
19577 default:
return false;
19581 if (Scale < 0) Scale = -Scale;
19589 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19602 if (Scale & 1)
return false;
19615 if (!Subtarget->isThumb())
19618 if (Subtarget->isThumb2())
19622 return Imm >= 0 && Imm <= 255;
19632 if (!Subtarget->isThumb())
19634 if (Subtarget->isThumb2())
19637 return AbsImm <= 255;
19672 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19676 int RHSC = (int)
RHS->getZExtValue();
19677 if (RHSC < 0 && RHSC > -256) {
19687 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19690 int RHSC = (int)
RHS->getZExtValue();
19691 if (RHSC < 0 && RHSC > -0x1000) {
19733 int RHSC = (int)
RHS->getZExtValue();
19734 if (RHSC < 0 && RHSC > -0x100) {
19739 }
else if (RHSC > 0 && RHSC < 0x100) {
19750 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19761 bool CanChangeType = isLE && !IsMasked;
19764 int RHSC = (int)
RHS->getZExtValue();
19766 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19767 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19772 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19783 if (VT == MVT::v4i16) {
19784 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19786 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19787 if (IsInRange(RHSC, 0x80, 1))
19789 }
else if (Alignment >= 4 &&
19790 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19791 IsInRange(RHSC, 0x80, 4))
19793 else if (Alignment >= 2 &&
19794 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19795 IsInRange(RHSC, 0x80, 2))
19797 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19810 if (Subtarget->isThumb1Only())
19816 bool isSEXTLoad =
false;
19817 bool IsMasked =
false;
19819 Ptr = LD->getBasePtr();
19820 VT = LD->getMemoryVT();
19821 Alignment = LD->getAlign();
19824 Ptr = ST->getBasePtr();
19825 VT = ST->getMemoryVT();
19826 Alignment = ST->getAlign();
19828 Ptr = LD->getBasePtr();
19829 VT = LD->getMemoryVT();
19830 Alignment = LD->getAlign();
19834 Ptr = ST->getBasePtr();
19835 VT = ST->getMemoryVT();
19836 Alignment = ST->getAlign();
19842 bool isLegal =
false;
19844 isLegal = Subtarget->hasMVEIntegerOps() &&
19846 Ptr.getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19847 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19849 if (Subtarget->isThumb2())
19874 bool isSEXTLoad =
false, isNonExt;
19875 bool IsMasked =
false;
19877 VT = LD->getMemoryVT();
19878 Ptr = LD->getBasePtr();
19879 Alignment = LD->getAlign();
19883 VT = ST->getMemoryVT();
19884 Ptr = ST->getBasePtr();
19885 Alignment = ST->getAlign();
19886 isNonExt = !ST->isTruncatingStore();
19888 VT = LD->getMemoryVT();
19889 Ptr = LD->getBasePtr();
19890 Alignment = LD->getAlign();
19895 VT = ST->getMemoryVT();
19896 Ptr = ST->getBasePtr();
19897 Alignment = ST->getAlign();
19898 isNonExt = !ST->isTruncatingStore();
19903 if (Subtarget->isThumb1Only()) {
19906 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19907 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19910 if (!RHS || RHS->getZExtValue() != 4)
19912 if (Alignment <
Align(4))
19916 Base =
Op->getOperand(0);
19922 bool isLegal =
false;
19924 isLegal = Subtarget->hasMVEIntegerOps() &&
19929 if (Subtarget->isThumb2())
19943 !Subtarget->isThumb2())
19957 const APInt &DemandedElts,
19959 unsigned Depth)
const {
19962 switch (
Op.getOpcode()) {
19969 if (
Op.getResNo() == 0) {
19995 case Intrinsic::arm_ldaex:
19996 case Intrinsic::arm_ldrex: {
20011 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20012 Known.
Zero &= Mask;
20018 const SDValue &SrcSV =
Op.getOperand(0);
20024 "VGETLANE index out of bounds");
20029 EVT VT =
Op.getValueType();
20036 Known = Known.
sext(DstSz);
20038 Known = Known.
zext(DstSz);
20046 Known = KnownOp.
zext(32);
20073 unsigned Encoded =
Op.getConstantOperandVal(1);
20074 unsigned DecEltBits = 0;
20077 unsigned EltBits =
Op.getScalarValueSizeInBits();
20078 if (EltBits != DecEltBits) {
20088 APInt Imm(DecEltBits, DecodedVal);
20090 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20091 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20109 EVT VT =
Op.getValueType();
20115 assert(VT == MVT::i32 &&
"Unexpected integer type");
20122 unsigned Mask =
C->getZExtValue();
20125 unsigned ShrunkMask = Mask & Demanded;
20126 unsigned ExpandedMask = Mask | ~Demanded;
20130 if (ShrunkMask == 0)
20136 if (ExpandedMask == ~0U)
20139 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20140 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20142 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20143 if (NewMask == Mask)
20152 if (IsLegalMask(0xFF))
20153 return UseMask(0xFF);
20156 if (IsLegalMask(0xFFFF))
20157 return UseMask(0xFFFF);
20161 if (ShrunkMask < 256)
20162 return UseMask(ShrunkMask);
20166 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20167 return UseMask(ExpandedMask);
20182 unsigned Depth)
const {
20183 unsigned Opc =
Op.getOpcode();
20191 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20193 unsigned ShAmt =
Op->getConstantOperandVal(2);
20205 unsigned ModImm =
Op.getConstantOperandVal(1);
20206 unsigned EltBits = 0;
20208 if ((OriginalDemandedBits & Mask) == 0)
20214 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20229 if (!Subtarget->hasVFP2Base())
20233 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20245 unsigned S = Constraint.
size();
20247 switch (Constraint[0]) {
20259 }
else if (S == 2) {
20260 switch (Constraint[0]) {
20277 Value *CallOperandVal =
info.CallOperandVal;
20280 if (!CallOperandVal)
20284 switch (*constraint) {
20290 if (Subtarget->isThumb())
20305 if (PR == 0 || VT == MVT::Other)
20307 return (ARM::SPRRegClass.
contains(PR) && VT != MVT::f32 && VT != MVT::i32) ||
20308 (ARM::DPRRegClass.contains(PR) && VT != MVT::f64 &&
20312using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20316 switch (Constraint.
size()) {
20319 switch (Constraint[0]) {
20321 if (Subtarget->isThumb())
20322 return RCPair(0U, &ARM::tGPRRegClass);
20323 return RCPair(0U, &ARM::GPRRegClass);
20325 if (Subtarget->isThumb())
20326 return RCPair(0U, &ARM::hGPRRegClass);
20329 if (Subtarget->isThumb1Only())
20330 return RCPair(0U, &ARM::tGPRRegClass);
20331 return RCPair(0U, &ARM::GPRRegClass);
20333 if (VT == MVT::Other)
20335 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20336 return RCPair(0U, &ARM::SPRRegClass);
20338 return RCPair(0U, &ARM::DPRRegClass);
20340 return RCPair(0U, &ARM::QPRRegClass);
20343 if (VT == MVT::Other)
20345 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20346 return RCPair(0U, &ARM::SPR_8RegClass);
20348 return RCPair(0U, &ARM::DPR_8RegClass);
20350 return RCPair(0U, &ARM::QPR_8RegClass);
20353 if (VT == MVT::Other)
20355 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20356 return RCPair(0U, &ARM::SPRRegClass);
20358 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20360 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20366 if (Constraint[0] ==
'T') {
20367 switch (Constraint[1]) {
20371 return RCPair(0U, &ARM::tGPREvenRegClass);
20373 return RCPair(0U, &ARM::tGPROddRegClass);
20382 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20383 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20387 return {0,
nullptr};
20395 std::vector<SDValue> &
Ops,
20400 if (Constraint.
size() != 1)
20403 char ConstraintLetter = Constraint[0];
20404 switch (ConstraintLetter) {
20407 case 'I':
case 'J':
case 'K':
case 'L':
20408 case 'M':
case 'N':
case 'O':
20413 int64_t CVal64 =
C->getSExtValue();
20414 int CVal = (int) CVal64;
20417 if (CVal != CVal64)
20420 switch (ConstraintLetter) {
20424 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20425 if (CVal >= 0 && CVal <= 65535)
20429 if (Subtarget->isThumb1Only()) {
20432 if (CVal >= 0 && CVal <= 255)
20434 }
else if (Subtarget->isThumb2()) {
20448 if (Subtarget->isThumb1Only()) {
20453 if (CVal >= -255 && CVal <= -1)
20459 if (CVal >= -4095 && CVal <= 4095)
20465 if (Subtarget->isThumb1Only()) {
20472 }
else if (Subtarget->isThumb2()) {
20492 if (Subtarget->isThumb1Only()) {
20495 if (CVal >= -7 && CVal < 7)
20497 }
else if (Subtarget->isThumb2()) {
20517 if (Subtarget->isThumb1Only()) {
20520 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20526 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20532 if (Subtarget->isThumb1Only()) {
20534 if (CVal >= 0 && CVal <= 31)
20540 if (Subtarget->isThumb1Only()) {
20543 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20552 if (Result.getNode()) {
20553 Ops.push_back(Result);
20563 "Unhandled Opcode in getDivRemLibcall");
20569 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20570 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20571 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20572 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20581 "Unhandled Opcode in getDivRemArgList");
20585 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20586 EVT ArgVT =
N->getOperand(i).getValueType();
20591 Args.push_back(Entry);
20599 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20600 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20601 Subtarget->isTargetWindows()) &&
20602 "Register-based DivRem lowering only");
20603 unsigned Opcode =
Op->getOpcode();
20605 "Invalid opcode for Div/Rem lowering");
20607 EVT VT =
Op->getValueType(0);
20629 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20630 : Subtarget->hasDivideInARMMode();
20631 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20632 Op->getSimpleValueType(0) == MVT::i32) {
20634 const SDValue Dividend =
Op->getOperand(0);
20635 const SDValue Divisor =
Op->getOperand(1);
20636 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20640 SDValue Values[2] = {Div, Rem};
20657 if (Subtarget->isTargetWindows())
20660 TargetLowering::CallLoweringInfo CLI(DAG);
20665 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20666 return CallInfo.first;
20672 EVT VT =
N->getValueType(0);
20678 Result[0], Result[1]);
20682 std::vector<Type*> RetTyParams;
20683 Type *RetTyElement;
20693 RetTyParams.push_back(RetTyElement);
20694 RetTyParams.push_back(RetTyElement);
20707 if (Subtarget->isTargetWindows())
20715 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20718 SDNode *ResNode = CallResult.first.getNode();
20725 assert(Subtarget->isTargetWindows() &&
"unsupported target platform");
20733 "no-stack-arg-probe")) {
20737 Chain =
SP.getValue(1);
20754 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20765 bool IsStrict =
Op->isStrictFPOpcode();
20766 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20767 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20769 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20770 "Unexpected type for custom-lowering FP_EXTEND");
20772 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20773 "With both FP DP and 16, any FP conversion is legal!");
20775 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20776 "With FP16, 16 to 32 conversion is legal!");
20779 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20784 Loc,
Op.getValueType(), SrcVal);
20799 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20800 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20801 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20802 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20806 {DstVT, MVT::Other}, {Chain, SrcVal});
20809 SrcVal = DAG.
getNode(ISD::FP_EXTEND, Loc, DstVT, SrcVal);
20813 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20814 "Unexpected type for custom-lowering FP_EXTEND");
20815 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20820 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20824 bool IsStrict =
Op->isStrictFPOpcode();
20826 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20828 EVT DstVT =
Op.getValueType();
20829 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20832 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20833 "Unexpected type for custom-lowering FP_ROUND");
20835 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20836 "With both FP DP and 16, any FP conversion is legal!");
20841 if (SrcSz == 32 && Subtarget->hasFP16())
20846 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20847 "Unexpected type for custom-lowering FP_ROUND");
20851 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20863 if (v == 0xffffffff)
20875 bool ForCodeSize)
const {
20876 if (!Subtarget->hasVFP3Base())
20878 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20880 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20883 if (VT == MVT::f32)
20885 if (VT == MVT::f64 && Subtarget->hasFP64())
20898 case Intrinsic::arm_neon_vld1:
20899 case Intrinsic::arm_neon_vld2:
20900 case Intrinsic::arm_neon_vld3:
20901 case Intrinsic::arm_neon_vld4:
20902 case Intrinsic::arm_neon_vld2lane:
20903 case Intrinsic::arm_neon_vld3lane:
20904 case Intrinsic::arm_neon_vld4lane:
20905 case Intrinsic::arm_neon_vld2dup:
20906 case Intrinsic::arm_neon_vld3dup:
20907 case Intrinsic::arm_neon_vld4dup: {
20910 auto &
DL =
I.getDataLayout();
20911 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20913 Info.ptrVal =
I.getArgOperand(0);
20915 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20921 case Intrinsic::arm_neon_vld1x2:
20922 case Intrinsic::arm_neon_vld1x3:
20923 case Intrinsic::arm_neon_vld1x4: {
20926 auto &
DL =
I.getDataLayout();
20927 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20929 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20931 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20936 case Intrinsic::arm_neon_vst1:
20937 case Intrinsic::arm_neon_vst2:
20938 case Intrinsic::arm_neon_vst3:
20939 case Intrinsic::arm_neon_vst4:
20940 case Intrinsic::arm_neon_vst2lane:
20941 case Intrinsic::arm_neon_vst3lane:
20942 case Intrinsic::arm_neon_vst4lane: {
20945 auto &
DL =
I.getDataLayout();
20946 unsigned NumElts = 0;
20947 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20948 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20951 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20954 Info.ptrVal =
I.getArgOperand(0);
20956 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20962 case Intrinsic::arm_neon_vst1x2:
20963 case Intrinsic::arm_neon_vst1x3:
20964 case Intrinsic::arm_neon_vst1x4: {
20967 auto &
DL =
I.getDataLayout();
20968 unsigned NumElts = 0;
20969 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20970 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20973 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20976 Info.ptrVal =
I.getArgOperand(0);
20978 Info.align =
I.getParamAlign(0).valueOrOne();
20983 case Intrinsic::arm_mve_vld2q:
20984 case Intrinsic::arm_mve_vld4q: {
20988 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
20990 Info.ptrVal =
I.getArgOperand(0);
20997 case Intrinsic::arm_mve_vst2q:
20998 case Intrinsic::arm_mve_vst4q: {
21001 Type *VecTy =
I.getArgOperand(1)->getType();
21002 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21004 Info.ptrVal =
I.getArgOperand(0);
21011 case Intrinsic::arm_mve_vldr_gather_base:
21012 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21014 Info.ptrVal =
nullptr;
21016 Info.align =
Align(1);
21020 case Intrinsic::arm_mve_vldr_gather_base_wb:
21021 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21023 Info.ptrVal =
nullptr;
21024 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21025 Info.align =
Align(1);
21029 case Intrinsic::arm_mve_vldr_gather_offset:
21030 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21032 Info.ptrVal =
nullptr;
21037 Info.align =
Align(1);
21041 case Intrinsic::arm_mve_vstr_scatter_base:
21042 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21044 Info.ptrVal =
nullptr;
21045 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21046 Info.align =
Align(1);
21050 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21051 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21053 Info.ptrVal =
nullptr;
21054 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21055 Info.align =
Align(1);
21059 case Intrinsic::arm_mve_vstr_scatter_offset:
21060 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21062 Info.ptrVal =
nullptr;
21067 Info.align =
Align(1);
21071 case Intrinsic::arm_ldaex:
21072 case Intrinsic::arm_ldrex: {
21073 auto &
DL =
I.getDataLayout();
21074 Type *ValTy =
I.getParamElementType(0);
21077 Info.ptrVal =
I.getArgOperand(0);
21079 Info.align =
DL.getABITypeAlign(ValTy);
21083 case Intrinsic::arm_stlex:
21084 case Intrinsic::arm_strex: {
21085 auto &
DL =
I.getDataLayout();
21086 Type *ValTy =
I.getParamElementType(1);
21089 Info.ptrVal =
I.getArgOperand(1);
21091 Info.align =
DL.getABITypeAlign(ValTy);
21095 case Intrinsic::arm_stlexd:
21096 case Intrinsic::arm_strexd:
21098 Info.memVT = MVT::i64;
21099 Info.ptrVal =
I.getArgOperand(2);
21101 Info.align =
Align(8);
21105 case Intrinsic::arm_ldaexd:
21106 case Intrinsic::arm_ldrexd:
21108 Info.memVT = MVT::i64;
21109 Info.ptrVal =
I.getArgOperand(0);
21111 Info.align =
Align(8);
21126 assert(Ty->isIntegerTy());
21128 unsigned Bits = Ty->getPrimitiveSizeInBits();
21129 if (Bits == 0 || Bits > 32)
21135 unsigned Index)
const {
21145 if (!Subtarget->hasDataBarrier()) {
21149 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21150 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21151 Builder.getInt32(0), Builder.getInt32(7),
21152 Builder.getInt32(10), Builder.getInt32(5)};
21153 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
21163 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
21184 if (Subtarget->preferISHSTBarriers())
21217 bool has64BitAtomicStore;
21218 if (Subtarget->isMClass())
21219 has64BitAtomicStore =
false;
21220 else if (Subtarget->isThumb())
21221 has64BitAtomicStore = Subtarget->hasV7Ops();
21223 has64BitAtomicStore = Subtarget->hasV6Ops();
21225 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21239 bool has64BitAtomicLoad;
21240 if (Subtarget->isMClass())
21241 has64BitAtomicLoad =
false;
21242 else if (Subtarget->isThumb())
21243 has64BitAtomicLoad = Subtarget->hasV7Ops();
21245 has64BitAtomicLoad = Subtarget->hasV6Ops();
21261 if (Subtarget->isMClass())
21262 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21263 else if (Subtarget->isThumb())
21264 hasAtomicRMW = Subtarget->hasV7Ops();
21266 hasAtomicRMW = Subtarget->hasV6Ops();
21267 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21290 bool HasAtomicCmpXchg;
21291 if (Subtarget->isMClass())
21292 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21293 else if (Subtarget->isThumb())
21294 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21296 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21298 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21305 return InsertFencesForAtomic;
21310 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21314 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21316 if (SecurityCheckCookieLibcall == RTLIB::Unsupported)
21320 M.getOrInsertGlobal(
"__security_cookie",
21328 F->addParamAttr(0, Attribute::AttrKind::InReg);
21333 RTLIB::LibcallImpl SecurityCheckCookie =
21335 if (SecurityCheckCookie != RTLIB::Unsupported)
21341 unsigned &
Cost)
const {
21343 if (!Subtarget->hasNEON())
21372 unsigned Opcode =
Op.getOpcode();
21383 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21387 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21392 if (!Subtarget->hasV7Ops())
21398 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21400 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21408 if (Subtarget->hasMinSize() && !Subtarget->isTargetWindows())
21417 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21423 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21425 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21428 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21430 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21431 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21432 if (!Subtarget->isLittle())
21434 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21435 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21436 return Builder.CreateOr(
21437 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21441 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21442 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21445 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21446 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21451 if (!Subtarget->hasV7Ops())
21453 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21459 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21467 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21471 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21472 if (!Subtarget->isLittle())
21474 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21477 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21481 CallInst *CI = Builder.CreateCall(
21482 Strex, {Builder.CreateZExtOrBitCast(
21492 return Subtarget->isMClass();
21500 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21507 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21510 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21518 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21526 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21529 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21534 if (Subtarget->hasNEON() && VecSize == 64)
21536 return VecSize % 128 == 0;
21540 if (Subtarget->hasNEON())
21542 if (Subtarget->hasMVEIntegerOps())
21562 "Invalid interleave factor");
21563 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21565 "Unmatched number of shufflevectors and indices");
21570 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21573 Type *EltTy = VecTy->getElementType();
21576 Align Alignment = LI->getAlign();
21594 Value *BaseAddr = LI->getPointerOperand();
21596 if (NumLoads > 1) {
21600 VecTy->getNumElements() / NumLoads);
21606 if (Subtarget->hasNEON()) {
21607 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21608 Type *Tys[] = {VecTy, PtrTy};
21609 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21610 Intrinsic::arm_neon_vld3,
21611 Intrinsic::arm_neon_vld4};
21614 Ops.push_back(BaseAddr);
21615 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21617 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21620 assert((Factor == 2 || Factor == 4) &&
21621 "expected interleave factor of 2 or 4 for MVE");
21623 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21624 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21625 Type *Tys[] = {VecTy, PtrTy};
21628 Ops.push_back(BaseAddr);
21629 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21639 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21643 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21644 VecTy->getNumElements() * Factor);
21650 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21652 unsigned Index = Indices[i];
21654 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21658 SubVec = Builder.CreateIntToPtr(
21662 SubVecs[SV].push_back(SubVec);
21671 auto &SubVec = SubVecs[SVI];
21674 SVI->replaceAllUsesWith(WideVec);
21710 const APInt &GapMask)
const {
21712 "Invalid interleave factor");
21717 "Unexpected mask on store");
21720 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21722 unsigned LaneLen = VecTy->getNumElements() / Factor;
21723 Type *EltTy = VecTy->getElementType();
21727 Align Alignment =
SI->getAlign();
21744 Type *IntTy =
DL.getIntPtrType(EltTy);
21749 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21750 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21756 Value *BaseAddr =
SI->getPointerOperand();
21758 if (NumStores > 1) {
21761 LaneLen /= NumStores;
21771 if (Subtarget->hasNEON()) {
21772 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21773 Intrinsic::arm_neon_vst3,
21774 Intrinsic::arm_neon_vst4};
21775 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21776 Type *Tys[] = {PtrTy, SubVecTy};
21779 Ops.push_back(BaseAddr);
21781 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21782 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21784 assert((Factor == 2 || Factor == 4) &&
21785 "expected interleave factor of 2 or 4 for MVE");
21787 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21788 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21789 Type *Tys[] = {PtrTy, SubVecTy};
21792 Ops.push_back(BaseAddr);
21794 for (
unsigned F = 0;
F < Factor;
F++) {
21795 Ops.push_back(Builder.getInt32(
F));
21796 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21802 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21805 if (StoreCount > 0)
21806 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21807 BaseAddr, LaneLen * Factor);
21812 for (
unsigned i = 0; i < Factor; i++) {
21813 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21814 if (Mask[IdxI] >= 0) {
21815 Shuffles.
push_back(Builder.CreateShuffleVector(
21818 unsigned StartMask = 0;
21819 for (
unsigned j = 1; j < LaneLen; j++) {
21820 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21821 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21822 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21832 Shuffles.
push_back(Builder.CreateShuffleVector(
21853 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21857 Members += SubMembers;
21863 Members += SubMembers * AT->getNumElements();
21864 }
else if (Ty->isFloatTy()) {
21869 }
else if (Ty->isDoubleTy()) {
21881 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21883 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21885 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21898 return (Members > 0 && Members <= 4);
21904 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21906 return ABITypeAlign;
21911 assert(StackAlign &&
"data layout string is missing stack alignment");
21912 return std::min(ABITypeAlign, *StackAlign);
21921 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21930 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
21931 return IsHA || IsIntArray;
21935 const Constant *PersonalityFn)
const {
21943 const Constant *PersonalityFn)
const {
21956void ARMTargetLowering::insertCopiesSplitCSR(
21960 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21970 RC = &ARM::GPRRegClass;
21971 else if (ARM::DPRRegClass.
contains(*
I))
21972 RC = &ARM::DPRRegClass;
21982 assert(Entry->getParent()->getFunction().hasFnAttribute(
21983 Attribute::NoUnwind) &&
21984 "Function should be nounwind in insertCopiesSplitCSR!");
21985 Entry->addLiveIn(*
I);
21990 for (
auto *Exit : Exits)
21992 TII->get(TargetOpcode::COPY), *
I)
22003 return Subtarget->hasMVEIntegerOps();
22013 unsigned NumElements = VTy->getNumElements();
22020 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22021 return Subtarget->hasMVEFloatOps();
22026 return Subtarget->hasMVEIntegerOps() &&
22027 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22028 ScalarTy->isIntegerTy(32));
22038 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22040 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22042 if (TyWidth > 128) {
22043 int Stride = Ty->getNumElements() / 2;
22047 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22049 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22050 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22051 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22052 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22053 Value *LowerSplitAcc =
nullptr;
22054 Value *UpperSplitAcc =
nullptr;
22057 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22058 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22062 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22064 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22066 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22067 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22074 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22077 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22079 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22080 {ConstRotation, InputB, InputA});
22085 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22088 ConstRotation = ConstantInt::get(IntTy, 0);
22090 ConstRotation = ConstantInt::get(IntTy, 1);
22092 if (!ConstRotation)
22095 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22096 {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 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 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 found DebugLoc that has a DILocation, 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)
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.
virtual const ARMBaseRegisterInfo & getRegisterInfo() const =0
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 shouldExpandCmpUsingSelects(EVT VT) const override
Should we expand [US]CMP nodes using two selects and two compares, or by doing arithmetic on boolean ...
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...
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...
Function * getSSPStackGuardCheck(const Module &M) const override
If the target has a standard stack protection check function that performs validation and error handl...
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 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 shouldFoldConstantShiftPairToMask(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to fold a pair of shifts into a mask.
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 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.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
const char * getTargetNodeName(unsigned Opcode) const override
This method returns the name of a target specific DAG node.
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
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.
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.
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)
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
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
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.
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()
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.
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),...
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 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.
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags)
Get the specified node if it's already available, or else return NULL.
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.
virtual Function * getSSPStackGuardCheck(const Module &M) const
If the target has a standard stack protection check function that performs validation and error handl...
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked store does or does not work with the specified type and in...
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
static StringRef getLibcallImplName(RTLIB::LibcallImpl Call)
Get the libcall routine name for the specified libcall implementation.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl)
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
virtual void insertSSPDeclarations(Module &M) const
Inserts necessary declarations for SSP (stack protection) purpose.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool expandDIVREMByConstant(SDNode *N, SmallVectorImpl< SDValue > &Result, EVT HiLoVT, SelectionDAG &DAG, SDValue LL=SDValue(), SDValue LH=SDValue()) const
Attempt to expand an n-bit div/rem/divrem by constant using a n/2-bit urem by constant and other arit...
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual 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.
User * getUser() const
Returns the User that contains this Use.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
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.
@ 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],...
@ 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)
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)
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...
static constexpr roundingMode rmTowardZero
This struct is a compact representation of a valid (non-zero power of two) alignment.
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 ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
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
CallLoweringInfo & setDiscardResult(bool Value=true)
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)