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())
650 if (!Subtarget->isThumb1Only())
659 if (Subtarget->hasMVEIntegerOps())
660 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
663 if (Subtarget->hasLOB()) {
667 if (Subtarget->hasNEON()) {
668 addDRTypeForNEON(MVT::v2f32);
669 addDRTypeForNEON(MVT::v8i8);
670 addDRTypeForNEON(MVT::v4i16);
671 addDRTypeForNEON(MVT::v2i32);
672 addDRTypeForNEON(MVT::v1i64);
674 addQRTypeForNEON(MVT::v4f32);
675 addQRTypeForNEON(MVT::v2f64);
676 addQRTypeForNEON(MVT::v16i8);
677 addQRTypeForNEON(MVT::v8i16);
678 addQRTypeForNEON(MVT::v4i32);
679 addQRTypeForNEON(MVT::v2i64);
681 if (Subtarget->hasFullFP16()) {
682 addQRTypeForNEON(MVT::v8f16);
683 addDRTypeForNEON(MVT::v4f16);
686 if (Subtarget->hasBF16()) {
687 addQRTypeForNEON(MVT::v8bf16);
688 addDRTypeForNEON(MVT::v4bf16);
692 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
732 if (Subtarget->hasNEON()) {
773 ISD::FRINT, ISD::FTRUNC, ISD::FROUNDEVEN}) {
845 if (!Subtarget->hasVFP4Base()) {
854 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
863 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
872 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
880 if (Subtarget->hasMVEIntegerOps()) {
885 if (Subtarget->hasMVEFloatOps()) {
889 if (!Subtarget->hasFP64()) {
934 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
937 if (Subtarget->hasFullFP16()) {
943 if (!Subtarget->hasFP16()) {
969 if (!Subtarget->isThumb1Only()) {
994 if (Subtarget->hasDSP()) {
1004 if (Subtarget->hasBaseDSP()) {
1012 if (Subtarget->isThumb1Only()) {
1016 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
1017 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1032 if (Subtarget->hasMVEIntegerOps())
1036 if (Subtarget->isThumb1Only()) {
1042 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1056 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1065 if (Subtarget->hasPerfMon())
1069 if (!Subtarget->hasV6Ops())
1072 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1073 : Subtarget->hasDivideInARMMode();
1080 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1092 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1093 TT.isTargetMuslAEABI() || TT.isOSWindows()) {
1096 HasStandaloneRem =
false;
1123 if (TT.isOSWindows())
1130 InsertFencesForAtomic =
false;
1131 if (Subtarget->hasAnyDataBarrier() &&
1132 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1136 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1141 if (!Subtarget->hasAcquireRelease() ||
1144 InsertFencesForAtomic =
true;
1150 if (Subtarget->hasDataBarrier())
1151 InsertFencesForAtomic =
true;
1171 if (!InsertFencesForAtomic) {
1178 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1190 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1191 Subtarget->hasForced32BitAtomics()) {
1205 if (!Subtarget->hasV6Ops()) {
1211 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1212 !Subtarget->isThumb1Only()) {
1241 if (Subtarget->hasFullFP16()) {
1251 if (Subtarget->hasFullFP16())
1266 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1267 !Subtarget->isThumb1Only()) {
1274 if (!Subtarget->hasVFP4Base()) {
1280 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1282 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1288 if (!Subtarget->hasFP16()) {
1310 if (Subtarget->hasFPARMv8Base()) {
1320 if (Subtarget->hasNEON()) {
1327 if (Subtarget->hasFP64()) {
1341 if (Subtarget->hasFullFP16()) {
1366 if (Subtarget->hasNEON()) {
1378 if (Subtarget->hasV8Ops()) {
1393 if (Subtarget->hasFullFP16()) {
1421 if (TT.isOSWindows()) {
1438 if (Subtarget->hasMVEIntegerOps())
1441 if (Subtarget->hasV6Ops())
1443 if (Subtarget->isThumb1Only())
1446 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1447 Subtarget->isThumb2()) {
1453 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1454 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1476 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1482 return Subtarget->useSoftFloat();
1486 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1499std::pair<const TargetRegisterClass *, uint8_t>
1510 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1511 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1512 RRC = &ARM::DPRRegClass;
1517 if (Subtarget->useNEONForSinglePrecisionFP())
1520 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1521 case MVT::v4f32:
case MVT::v2f64:
1522 RRC = &ARM::DPRRegClass;
1526 RRC = &ARM::DPRRegClass;
1530 RRC = &ARM::DPRRegClass;
1534 return std::make_pair(RRC,
Cost);
1538#define MAKE_CASE(V) \
1757 if ((Subtarget->hasMVEIntegerOps() &&
1758 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1759 VT == MVT::v16i8)) ||
1760 (Subtarget->hasMVEFloatOps() &&
1761 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1775 if (Subtarget->hasNEON()) {
1776 if (VT == MVT::v4i64)
1777 return &ARM::QQPRRegClass;
1778 if (VT == MVT::v8i64)
1779 return &ARM::QQQQPRRegClass;
1781 if (Subtarget->hasMVEIntegerOps()) {
1782 if (VT == MVT::v4i64)
1783 return &ARM::MQQPRRegClass;
1784 if (VT == MVT::v8i64)
1785 return &ARM::MQQQQPRRegClass;
1794 Align &PrefAlign)
const {
1801 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1813 unsigned NumVals =
N->getNumValues();
1817 for (
unsigned i = 0; i != NumVals; ++i) {
1818 EVT VT =
N->getValueType(i);
1819 if (VT == MVT::Glue || VT == MVT::Other)
1825 if (!
N->isMachineOpcode())
1833 if (
MCID.getNumDefs() == 0)
1835 if (!Itins->isEmpty() &&
1836 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1850 return Const->getZExtValue() == 16;
1858 return Const->getZExtValue() == 16;
1866 return Const->getZExtValue() == 16;
1935 bool isVarArg)
const {
1954 if (!
getTM().isAAPCS_ABI())
1956 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1964 if (!
getTM().isAAPCS_ABI()) {
1965 if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() && !isVarArg)
1968 }
else if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() &&
1977 bool isVarArg)
const {
1978 return CCAssignFnForNode(CC,
false, isVarArg);
1982 bool isVarArg)
const {
1983 return CCAssignFnForNode(CC,
true, isVarArg);
1990 bool isVarArg)
const {
1991 switch (getEffectiveCallingConv(CC, isVarArg)) {
2017 if (Subtarget->hasFullFP16()) {
2022 Val = DAG.
getNode(ISD::BITCAST, dl, ValVT, Val);
2030 if (Subtarget->hasFullFP16()) {
2034 Val = DAG.
getNode(ISD::BITCAST, dl,
2039 return DAG.
getNode(ISD::BITCAST, dl, LocVT, Val);
2044SDValue ARMTargetLowering::LowerCallResult(
2048 SDValue ThisVal,
bool isCmseNSCall)
const {
2056 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
2057 CCValAssign VA = RVLocs[i];
2061 if (i == 0 && isThisReturn) {
2063 "unexpected return calling convention register assignment");
2081 if (!Subtarget->isLittle())
2098 if (!Subtarget->isLittle())
2141std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
2143 bool IsTailCall,
int SPDiff)
const {
2145 MachinePointerInfo DstInfo;
2165 return std::make_pair(DstAddr, DstInfo);
2174ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
2187 if (!SrcFrameIdxNode || !DstFrameIdxNode)
2190 int SrcFI = SrcFrameIdxNode->getIndex();
2191 int DstFI = DstFrameIdxNode->getIndex();
2193 "byval passed in non-fixed stack slot");
2215 if (SrcOffset == DstOffset)
2223 RegsToPassVector &RegsToPass,
2230 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
2231 unsigned id = Subtarget->isLittle() ? 0 : 1;
2243 MachinePointerInfo DstInfo;
2244 std::tie(DstAddr, DstInfo) =
2245 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2262 SelectionDAG &DAG = CLI.
DAG;
2264 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2265 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2266 SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2273 const CallBase *CB = CLI.
CB;
2276 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2278 MachineFunction::CallSiteInfo CSInfo;
2279 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2280 bool isThisReturn =
false;
2281 bool isCmseNSCall =
false;
2282 bool isSibCall =
false;
2283 bool PreferIndirect =
false;
2284 bool GuardWithBTI =
false;
2294 !Subtarget->noBTIAtReturnTwice())
2299 CSInfo = MachineFunction::CallSiteInfo(*CB);
2303 isCmseNSCall =
true;
2306 if (!Subtarget->supportsTailCall())
2322 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2323 count_if(GV->users(), [&BB](
const User *U) {
2324 return isa<Instruction>(U) &&
2325 cast<Instruction>(U)->getParent() == BB;
2332 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2346 "site marked musttail");
2349 unsigned NumBytes = CCInfo.getStackSize();
2358 if (isTailCall && !isSibCall) {
2359 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2360 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2365 assert(StackAlign &&
"data layout string is missing stack alignment");
2366 NumBytes =
alignTo(NumBytes, *StackAlign);
2371 SPDiff = NumReusableBytes - NumBytes;
2375 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2391 RegsToPassVector RegsToPass;
2400 DenseMap<unsigned, SDValue> ByValTemporaries;
2404 for (
const CCValAssign &VA : ArgLocs) {
2406 SDValue Src = OutVals[ArgIdx];
2407 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2409 if (!
Flags.isByVal())
2413 MachinePointerInfo DstInfo;
2414 std::tie(Dst, DstInfo) =
2415 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2416 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2418 if (Copy == NoCopy) {
2423 }
else if (Copy == CopyOnce) {
2427 ByValTemporaries[ArgIdx] = Src;
2429 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2433 int TempFrameIdx = MFI.CreateStackObject(
2434 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2442 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2443 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2446 ByValTemporaries[ArgIdx] = Temp;
2449 if (!ByValCopyChains.
empty())
2459 bool AfterFormalArgLoads =
false;
2463 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2465 ++i, ++realArgIdx) {
2466 CCValAssign &VA = ArgLocs[i];
2467 SDValue Arg = OutVals[realArgIdx];
2468 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2469 bool isByVal =
Flags.isByVal();
2489 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2494 AfterFormalArgLoads =
true;
2506 auto ArgVT = Outs[realArgIdx].ArgVT;
2507 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2525 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2526 StackPtr, MemOpChains, isTailCall, SPDiff);
2530 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2531 StackPtr, MemOpChains, isTailCall, SPDiff);
2535 MachinePointerInfo DstInfo;
2536 std::tie(DstAddr, DstInfo) =
2537 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2541 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2542 StackPtr, MemOpChains, isTailCall, SPDiff);
2544 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2545 Outs[0].VT == MVT::i32) {
2547 "unexpected calling convention register assignment");
2548 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2549 "unexpected use of 'returned'");
2550 isThisReturn =
true;
2555 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2556 }
else if (isByVal) {
2558 unsigned offset = 0;
2562 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2563 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2566 bool NeedsStackCopy;
2567 if (
auto It = ByValTemporaries.
find(realArgIdx);
2568 It != ByValTemporaries.
end()) {
2569 ByValSrc = It->second;
2570 NeedsStackCopy =
true;
2573 NeedsStackCopy = !isTailCall;
2577 if (CurByValIdx < ByValArgsCount) {
2578 unsigned RegBegin, RegEnd;
2579 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2583 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2587 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2590 RegsToPass.push_back(std::make_pair(j, Load));
2595 offset = RegEnd - RegBegin;
2597 CCInfo.nextInRegsParam();
2602 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2605 MachinePointerInfo DstInfo;
2606 std::tie(Dst, DstInfo) =
2607 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2615 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2616 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2623 MachinePointerInfo DstInfo;
2624 std::tie(DstAddr, DstInfo) =
2625 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2632 if (!MemOpChains.
empty())
2638 for (
const auto &[
Reg,
N] : RegsToPass) {
2646 bool isDirect =
false;
2649 const GlobalValue *GVal =
nullptr;
2651 GVal =
G->getGlobal();
2652 bool isStub = !TM.shouldAssumeDSOLocal(GVal) && Subtarget->isTargetMachO();
2654 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2655 bool isLocalARMFunc =
false;
2658 if (Subtarget->genLongCalls()) {
2660 "long-calls codegen is not position independent!");
2665 if (Subtarget->genExecuteOnly()) {
2666 if (Subtarget->useMovt())
2684 const char *Sym = S->getSymbol();
2686 if (Subtarget->genExecuteOnly()) {
2687 if (Subtarget->useMovt())
2706 if (!PreferIndirect) {
2711 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2713 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2714 assert(Subtarget->isTargetMachO() &&
"WrapperPIC use on non-MachO?");
2723 }
else if (Subtarget->isTargetCOFF()) {
2724 assert(Subtarget->isTargetWindows() &&
2725 "Windows is the only supported COFF target");
2729 else if (!TM.shouldAssumeDSOLocal(GVal))
2745 const char *Sym = S->getSymbol();
2746 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2748 ARMConstantPoolValue *CPV =
2750 ARMPCLabelIndex, 4);
2764 assert(!isARMFunc && !isDirect &&
2765 "Cannot handle call to ARM function or direct call");
2769 "call to non-secure function would require "
2770 "passing arguments on stack",
2776 "call to non-secure function would return value through pointer",
2783 if (Subtarget->isThumb()) {
2786 else if (isCmseNSCall)
2788 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2793 if (!isDirect && !Subtarget->hasV5TOps())
2795 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2797 !Subtarget->hasMinSize())
2808 if (isTailCall && !isSibCall) {
2813 std::vector<SDValue>
Ops;
2814 Ops.push_back(Chain);
2815 Ops.push_back(Callee);
2823 for (
const auto &[
Reg,
N] : RegsToPass)
2827 const uint32_t *
Mask;
2828 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2836 isThisReturn =
false;
2842 assert(Mask &&
"Missing call preserved mask for calling convention");
2846 Ops.push_back(InGlue);
2857 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2866 uint64_t CalleePopBytes =
2869 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2875 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2876 InVals, isThisReturn,
2877 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2884void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2885 Align Alignment)
const {
2887 Alignment = std::max(Alignment,
Align(4));
2893 unsigned AlignInRegs = Alignment.
value() / 4;
2894 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2895 for (
unsigned i = 0; i < Waste; ++i)
2901 unsigned Excess = 4 * (ARM::R4 -
Reg);
2908 if (NSAAOffset != 0 &&
Size > Excess) {
2920 unsigned ByValRegBegin =
Reg;
2921 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2925 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2931 Size = std::max<int>(
Size - Excess, 0);
2939bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2945 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2946 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2947 const SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2948 const SelectionDAG &DAG = CLI.
DAG;
2953 assert(Subtarget->supportsTailCall());
2966 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2968 if (!(Subtarget->isThumb1Only() ||
2969 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2970 AddressRegisters.
insert(ARM::R12);
2971 for (
const CCValAssign &AL : ArgLocs)
2973 AddressRegisters.
erase(
AL.getLocReg());
2974 if (AddressRegisters.
empty()) {
2975 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2994 <<
" (guaranteed tail-call CC)\n");
2995 return CalleeCC == CallerCC;
3000 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
3002 if (isCalleeStructRet != isCallerStructRet) {
3015 const GlobalValue *GV =
G->getGlobal();
3018 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
3019 TT.isOSBinFormatMachO())) {
3028 getEffectiveCallingConv(CalleeCC, isVarArg),
3029 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
3036 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3037 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
3038 if (CalleeCC != CallerCC) {
3039 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
3040 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
3049 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
3059 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
3078 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
3087 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
3100 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
3103 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
3107 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
3134 bool isLittleEndian = Subtarget->isLittle();
3137 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3146 "secure entry function would return value through pointer",
3151 for (
unsigned i = 0, realRVLocIdx = 0;
3153 ++i, ++realRVLocIdx) {
3154 CCValAssign &VA = RVLocs[i];
3157 SDValue Arg = OutVals[realRVLocIdx];
3158 bool ReturnF16 =
false;
3160 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
3193 auto RetVT = Outs[realRVLocIdx].ArgVT;
3215 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3219 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3225 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3237 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3239 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3244 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3254 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3280 !Subtarget->isMClass()) {
3281 if (Subtarget->isThumb1Only())
3288 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3291bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3292 if (
N->getNumValues() != 1)
3294 if (!
N->hasNUsesOfValue(1, 0))
3298 SDNode *
Copy = *
N->user_begin();
3302 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3304 TCChain =
Copy->getOperand(0);
3306 SDNode *VMov =
Copy;
3308 SmallPtrSet<SDNode*, 2>
Copies;
3309 for (SDNode *U : VMov->
users()) {
3317 for (SDNode *U : VMov->
users()) {
3318 SDValue UseChain =
U->getOperand(0);
3326 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3332 }
else if (
Copy->getOpcode() == ISD::BITCAST) {
3334 if (!
Copy->hasOneUse())
3341 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3343 TCChain =
Copy->getOperand(0);
3348 bool HasRet =
false;
3349 for (
const SDNode *U :
Copy->users()) {
3363bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3364 if (!Subtarget->supportsTailCall())
3381 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3397 EVT PtrVT =
Op.getValueType();
3407 if (Subtarget->genExecuteOnly()) {
3409 auto *
T =
CP->getType();
3410 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3412 auto GV =
new GlobalVariable(
3420 return LowerGlobalAddress(GA, DAG);
3425 Align CPAlign =
CP->getAlign();
3426 if (Subtarget->isThumb1Only())
3427 CPAlign = std::max(CPAlign,
Align(4));
3428 if (
CP->isMachineConstantPoolEntry())
3440 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3449 unsigned ARMPCLabelIndex = 0;
3455 if (!IsPositionIndependent) {
3458 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3469 if (!IsPositionIndependent)
3500ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3502 assert(Subtarget->isTargetDarwin() &&
3503 "This function expects a Darwin target");
3508 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3514 MVT::i32,
DL, Chain, DescAddr,
3529 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3538 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3544ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3546 assert(Subtarget->isTargetWindows() &&
"Windows specific TLS lowering");
3570 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3579 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3585 MachinePointerInfo());
3605 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3607 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3609 ARMConstantPoolValue *CPV =
3627 TargetLowering::CallLoweringInfo CLI(DAG);
3632 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3633 return CallResult.first;
3642 const GlobalValue *GV = GA->
getGlobal();
3652 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3655 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3656 ARMConstantPoolValue *CPV =
3663 PtrVT, dl, Chain,
Offset,
3671 PtrVT, dl, Chain,
Offset,
3676 ARMConstantPoolValue *CPV =
3681 PtrVT, dl, Chain,
Offset,
3696 if (Subtarget->isTargetDarwin())
3697 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3699 if (Subtarget->isTargetWindows())
3700 return LowerGlobalTLSAddressWindows(
Op, DAG);
3703 assert(Subtarget->isTargetELF() &&
"Only ELF implemented here");
3709 return LowerToTLSGeneralDynamicModel(GA, DAG);
3712 return LowerToTLSExecModels(GA, DAG, model);
3721 while (!Worklist.
empty()) {
3729 if (!
I ||
I->getParent()->getParent() !=
F)
3758 if (!GVar || !GVar->hasInitializer() ||
3759 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3760 !GVar->hasLocalLinkage())
3765 auto *
Init = GVar->getInitializer();
3767 Init->needsDynamicRelocation())
3779 unsigned RequiredPadding = 4 - (
Size % 4);
3780 bool PaddingPossible =
3781 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3786 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3810 if (RequiredPadding != 4) {
3815 while (RequiredPadding--)
3827 ++NumConstpoolPromoted;
3833 if (!(GV = GA->getAliaseeObject()))
3836 return V->isConstant();
3845 return LowerGlobalAddressWindows(
Op, DAG);
3847 return LowerGlobalAddressELF(
Op, DAG);
3849 return LowerGlobalAddressDarwin(
Op, DAG);
3861 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3874 }
else if (Subtarget->isROPI() && IsRO) {
3879 }
else if (Subtarget->isRWPI() && !IsRO) {
3882 if (Subtarget->useMovt()) {
3887 ARMConstantPoolValue *CPV =
3904 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3905 if (Subtarget->useMovt())
3922 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3923 "ROPI/RWPI not currently supported for Darwin");
3928 if (Subtarget->useMovt())
3939 if (Subtarget->isGVIndirectSymbol(GV))
3947 assert(Subtarget->isTargetWindows() &&
"non-Windows COFF is not supported");
3948 assert(Subtarget->useMovt() &&
3949 "Windows on ARM expects to use movw/movt");
3950 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3951 "ROPI/RWPI not currently supported for Windows");
3958 else if (!TM.shouldAssumeDSOLocal(GV))
3982 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3983 Op.getOperand(1), Val);
4000SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
4003 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
4007 case Intrinsic::arm_gnu_eabi_mcount: {
4013 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
4014 const uint32_t *
Mask =
4016 assert(Mask &&
"Missing call preserved mask for calling convention");
4021 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
4025 if (Subtarget->isThumb())
4028 ARM::tBL_PUSHLR, dl, ResultTys,
4029 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
4030 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
4034 {ReturnAddress, Callee, RegisterMask, Chain}),
4043 unsigned IntNo =
Op.getConstantOperandVal(0);
4047 case Intrinsic::thread_pointer: {
4051 case Intrinsic::arm_cls: {
4052 const SDValue &Operand =
Op.getOperand(1);
4053 const EVT VTy =
Op.getValueType();
4064 case Intrinsic::arm_cls64: {
4067 const SDValue &Operand =
Op.getOperand(1);
4068 const EVT VTy =
Op.getValueType();
4091 case Intrinsic::eh_sjlj_lsda: {
4093 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4098 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
4099 ARMConstantPoolValue *CPV =
4108 if (IsPositionIndependent) {
4114 case Intrinsic::arm_neon_vabs:
4117 case Intrinsic::arm_neon_vabds:
4118 if (
Op.getValueType().isInteger())
4120 Op.getOperand(1),
Op.getOperand(2));
4122 case Intrinsic::arm_neon_vabdu:
4124 Op.getOperand(1),
Op.getOperand(2));
4125 case Intrinsic::arm_neon_vmulls:
4126 case Intrinsic::arm_neon_vmullu: {
4127 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
4129 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4130 Op.getOperand(1),
Op.getOperand(2));
4132 case Intrinsic::arm_neon_vminnm:
4133 case Intrinsic::arm_neon_vmaxnm: {
4134 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
4135 ? ISD::FMINNUM : ISD::FMAXNUM;
4136 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4137 Op.getOperand(1),
Op.getOperand(2));
4139 case Intrinsic::arm_neon_vminu:
4140 case Intrinsic::arm_neon_vmaxu: {
4141 if (
Op.getValueType().isFloatingPoint())
4143 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
4145 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4146 Op.getOperand(1),
Op.getOperand(2));
4148 case Intrinsic::arm_neon_vmins:
4149 case Intrinsic::arm_neon_vmaxs: {
4151 if (!
Op.getValueType().isFloatingPoint()) {
4152 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4154 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4155 Op.getOperand(1),
Op.getOperand(2));
4157 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4158 ? ISD::FMINIMUM : ISD::FMAXIMUM;
4159 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4160 Op.getOperand(1),
Op.getOperand(2));
4162 case Intrinsic::arm_neon_vtbl1:
4164 Op.getOperand(1),
Op.getOperand(2));
4165 case Intrinsic::arm_neon_vtbl2:
4167 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4168 case Intrinsic::arm_mve_pred_i2v:
4169 case Intrinsic::arm_mve_pred_v2i:
4172 case Intrinsic::arm_mve_vreinterpretq:
4175 case Intrinsic::arm_mve_lsll:
4177 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4178 case Intrinsic::arm_mve_asrl:
4180 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4191 if (!Subtarget->hasDataBarrier()) {
4195 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4196 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4207 }
else if (Subtarget->preferISHSTBarriers() &&
4216 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4224 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4226 return Op.getOperand(0);
4229 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4231 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4233 return Op.getOperand(0);
4235 unsigned isData =
Op.getConstantOperandVal(4);
4236 if (Subtarget->isThumb()) {
4238 isRead = ~isRead & 1;
4239 isData = ~isData & 1;
4257 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4265 const SDLoc &dl)
const {
4267 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4269 const TargetRegisterClass *RC;
4271 RC = &ARM::tGPRRegClass;
4273 RC = &ARM::GPRRegClass;
4287 MVT::i32, dl, Root, FIN,
4293 if (!Subtarget->isLittle())
4308 const Value *OrigArg,
4309 unsigned InRegsParamRecordIdx,
4310 int ArgOffset,
unsigned ArgSize)
const {
4324 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4325 unsigned RBegin, REnd;
4330 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4335 ArgOffset = -4 * (ARM::R4 - RBegin);
4342 const TargetRegisterClass *RC =
4345 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4349 MachinePointerInfo(OrigArg, 4 * i));
4354 if (!MemOps.
empty())
4363 unsigned TotalArgRegsSaveSize,
4364 bool ForceMutable)
const {
4366 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4375 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4379bool ARMTargetLowering::splitValueIntoRegisterParts(
4381 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4383 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4388 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
4395SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4397 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4398 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4405 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
4411SDValue ARMTargetLowering::LowerFormalArguments(
4418 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4427 unsigned CurArgIdx = 0;
4439 unsigned ArgRegBegin = ARM::R4;
4440 for (
const CCValAssign &VA : ArgLocs) {
4446 if (!
Flags.isByVal())
4450 unsigned RBegin, REnd;
4452 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4458 int lastInsIndex = -1;
4462 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4465 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4469 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4470 CCValAssign &VA = ArgLocs[i];
4471 if (Ins[VA.
getValNo()].isOrigArg()) {
4472 std::advance(CurOrigArg,
4473 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4485 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4492 MVT::f64, dl, Chain, FIN,
4495 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4503 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4505 const TargetRegisterClass *RC;
4507 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4508 RC = &ARM::HPRRegClass;
4509 else if (RegVT == MVT::f32)
4510 RC = &ARM::SPRRegClass;
4511 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4512 RegVT == MVT::v4bf16)
4513 RC = &ARM::DPRRegClass;
4514 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4515 RegVT == MVT::v8bf16)
4516 RC = &ARM::QPRRegClass;
4517 else if (RegVT == MVT::i32)
4519 : &ARM::GPRRegClass;
4565 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4571 if (index != lastInsIndex)
4573 ISD::ArgFlagsTy
Flags =
Ins[index].Flags;
4579 if (
Flags.isByVal()) {
4580 assert(Ins[index].isOrigArg() &&
4581 "Byval arguments cannot be implicit");
4585 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4619 lastInsIndex = index;
4626 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4627 TotalArgRegsSaveSize);
4631 "secure entry function must not be variadic", dl.
getDebugLoc()));
4641 assert(StackAlign &&
"data layout string is missing stack alignment");
4642 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4651 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4660 return CFP->getValueAPF().isPosZero();
4664 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4667 return CFP->getValueAPF().isPosZero();
4669 }
else if (
Op->getOpcode() == ISD::BITCAST &&
4670 Op->getValueType(0) == MVT::f64) {
4685 const SDLoc &dl)
const {
4687 unsigned C = RHSC->getZExtValue();
4751 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4755 unsigned Mask =
LHS.getConstantOperandVal(1);
4757 uint64_t RHSV = RHSC->getZExtValue();
4758 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4760 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4774 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4777 LHS.getConstantOperandVal(1) < 31) {
4778 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4821 bool Signaling)
const {
4822 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4837std::pair<SDValue, SDValue>
4840 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4852 switch (
Op.getOpcode()) {
4904 return std::make_pair(
Value, OverflowCmp);
4915 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4920 EVT VT =
Op.getValueType();
4925 SDVTList VTs = DAG.
getVTList(
Op.getValueType(), MVT::i32);
4963 EVT VT =
Op.getValueType();
4964 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4967 switch (
Op.getOpcode()) {
4992 EVT VT =
Op.getValueType();
4993 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
5003 switch (
Op->getOpcode()) {
5019 switch (
Op->getOpcode()) {
5038 DAG.
getNode(NewOpcode, dl, MVT::i32,
5049 unsigned Opc =
Cond.getOpcode();
5051 if (
Cond.getResNo() == 1 &&
5059 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5060 EVT VT =
Op.getValueType();
5062 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
5071 const ConstantSDNode *CMOVTrue =
5073 const ConstantSDNode *CMOVFalse =
5076 if (CMOVTrue && CMOVFalse) {
5082 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5084 False = SelectFalse;
5085 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5091 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5092 Cond.getOperand(3), DAG);
5107 bool &swpCmpOps,
bool &swpVselOps) {
5135 swpCmpOps = !swpCmpOps;
5136 swpVselOps = !swpVselOps;
5159 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5161 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5163 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5198 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5200 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5221 EVT VT =
Op.getValueType();
5243 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5256 int64_t PosVal = std::max(Val1, Val2);
5257 int64_t NegVal = std::min(Val1, Val2);
5304 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5309 if (*K != KTmp || V != VTmp)
5320bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5322 return !Subtarget->hasVFP2Base();
5324 return !Subtarget->hasFP64();
5326 return !Subtarget->hasFullFP16();
5331 EVT VT =
Op.getValueType();
5335 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5347 if (VT == MVT::i32 &&
5367 if (
Op.getValueType().isInteger()) {
5375 LHS.getValueType() ==
RHS.getValueType()) {
5376 EVT VT =
LHS.getValueType();
5382 Shift = DAG.
getNOT(dl, Shift, VT);
5388 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5389 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5392 unsigned Opcode = 0;
5394 if (TVal == ~FVal) {
5396 }
else if (TVal == ~FVal + 1) {
5398 }
else if (TVal + 1 == FVal) {
5400 }
else if (TVal == FVal + 1) {
5431 EVT VT =
TrueVal.getValueType();
5432 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5436 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5441 if (!
RHS.getNode()) {
5447 if (
LHS.getValueType() == MVT::i32) {
5458 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5459 TrueVal.getValueType() == MVT::f32 ||
5460 TrueVal.getValueType() == MVT::f64)) {
5474 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5484 if (Subtarget->hasFPARMv8Base() &&
5486 (
TrueVal.getValueType() == MVT::f16 ||
5487 TrueVal.getValueType() == MVT::f32 ||
5488 TrueVal.getValueType() == MVT::f64)) {
5489 bool swpCmpOps =
false;
5490 bool swpVselOps =
false;
5504 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5507 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5517 if (!
N->hasOneUse())
5520 if (!
N->getNumValues())
5522 EVT VT =
Op.getValueType();
5523 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5540 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5541 Ld->getPointerInfo(), Ld->getAlign(),
5542 Ld->getMemOperand()->getFlags());
5560 DAG.
getLoad(MVT::i32, dl, Ld->getChain(),
Ptr, Ld->getPointerInfo(),
5561 Ld->getAlign(), Ld->getMemOperand()->getFlags());
5563 EVT PtrType =
Ptr.getValueType();
5566 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5567 Ld->getPointerInfo().getWithOffset(4),
5569 Ld->getMemOperand()->getFlags());
5587 bool LHSSeenZero =
false;
5589 bool RHSSeenZero =
false;
5591 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5602 if (
LHS.getValueType() == MVT::f32) {
5620 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5648 unsigned Opc =
Cond.getOpcode();
5650 !Subtarget->isThumb1Only();
5651 if (
Cond.getResNo() == 1 &&
5661 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5667 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5684 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5689 if (!
RHS.getNode()) {
5697 unsigned Opc =
LHS.getOpcode();
5699 !Subtarget->isThumb1Only();
5711 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5718 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5725 if (
LHS.getValueType() == MVT::i32) {
5731 SDNodeFlags
Flags =
Op->getFlags();
5737 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5768 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5774 Addr,
Op.getOperand(2), JTI);
5778 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5785 DAG.
getLoad(PTy, dl, Chain, Addr,
5793 EVT VT =
Op.getValueType();
5796 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5797 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5805 const EVT OpTy =
Op.getOperand(0).getValueType();
5806 if (OpTy == MVT::v4f32)
5808 else if (OpTy == MVT::v4f16 && HasFullFP16)
5810 else if (OpTy == MVT::v8f16 && HasFullFP16)
5815 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5818 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5823 EVT VT =
Op.getValueType();
5827 bool IsStrict =
Op->isStrictFPOpcode();
5828 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5830 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5843 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5844 CallOptions, Loc, Chain);
5854 Loc,
Op.getValueType(), SrcVal);
5863 EVT VT =
Op.getValueType();
5865 EVT FromVT =
Op.getOperand(0).getValueType();
5867 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5869 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5870 Subtarget->hasFP64())
5872 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5873 Subtarget->hasFullFP16())
5875 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5876 Subtarget->hasMVEFloatOps())
5878 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5879 Subtarget->hasMVEFloatOps())
5882 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5899 EVT VT =
Op.getValueType();
5902 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5908 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5909 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5910 "Invalid type for custom lowering!");
5915 if (VT == MVT::v4f32)
5916 DestVecType = MVT::v4i32;
5917 else if (VT == MVT::v4f16 && HasFullFP16)
5918 DestVecType = MVT::v4i16;
5919 else if (VT == MVT::v8f16 && HasFullFP16)
5920 DestVecType = MVT::v8i16;
5926 switch (
Op.getOpcode()) {
5938 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5943 EVT VT =
Op.getValueType();
5946 if (isUnsupportedFloatingType(VT)) {
5956 CallOptions, SDLoc(
Op)).first;
5967 EVT VT =
Op.getValueType();
5969 bool InGPR = Tmp0.
getOpcode() == ISD::BITCAST ||
5971 bool UseNEON = !InGPR && Subtarget->hasNEON();
5978 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5981 DAG.
getNode(ISD::BITCAST, dl, OpVT, Mask),
5985 if (SrcVT == MVT::f32) {
5989 DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1),
5991 }
else if (VT == MVT::f32)
5993 DAG.
getNode(ISD::BITCAST, dl, MVT::v1i64, Tmp1),
5995 Tmp0 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp0);
5996 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1);
6007 if (VT == MVT::f32) {
6008 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::v2f32, Res);
6012 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Res);
6019 if (SrcVT == MVT::f64)
6022 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp1);
6028 if (VT == MVT::f32) {
6030 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
6031 return DAG.
getNode(ISD::BITCAST, dl, MVT::f32,
6049 EVT VT =
Op.getValueType();
6051 unsigned Depth =
Op.getConstantOperandVal(0);
6053 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
6057 MachinePointerInfo());
6066 const ARMBaseRegisterInfo &ARI =
6067 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
6072 EVT VT =
Op.getValueType();
6074 unsigned Depth =
Op.getConstantOperandVal(0);
6079 MachinePointerInfo());
6087 return StringSwitch<Register>(
RegName)
6088 .Case(
"sp", ARM::SP)
6099 assert(
N->getValueType(0) == MVT::i64
6100 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6103 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6143 const APInt &APIntIndex = Index->getAPIntValue();
6145 NewIndex *= APIntIndex;
6157 SDValue BitCast = DAG.
getNode(ISD::BITCAST, dl, VecVT, ExtractSrc);
6174 EVT SrcVT =
Op.getValueType();
6175 EVT DstVT =
N->getValueType(0);
6177 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6178 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6179 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6182 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6183 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6184 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6191 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6202 return DAG.
getNode(ISD::BITCAST, dl, DstVT,
6236 return DAG.
getNode(ISD::BITCAST, dl, VT, Vmov);
6244 EVT VT =
Op.getValueType();
6287 EVT VT =
Op.getValueType();
6329 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6381 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6409 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6439 EVT VT =
N->getValueType(0);
6440 if (VT.
isVector() && ST->hasNEON()) {
6449 if (ElemTy == MVT::i8) {
6457 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6460 unsigned NumBits = ElemTy.getSizeInBits();
6472 if (ElemTy == MVT::i64) {
6485 if (!ST->hasV6T2Ops())
6494 EVT VT =
N->getValueType(0);
6497 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6498 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6499 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6500 "Unexpected type for custom ctpop lowering");
6508 unsigned EltSize = 8;
6530 while (
Op.getOpcode() == ISD::BITCAST)
6531 Op =
Op.getOperand(0);
6533 APInt SplatBits, SplatUndef;
6534 unsigned SplatBitSize;
6537 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6539 SplatBitSize > ElementBits)
6550 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6554 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6565 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6570 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6571 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6580 EVT VT =
N->getValueType(0);
6602 "unexpected vector shift opcode");
6604 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6605 unsigned VShiftOpc =
6607 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6613 EVT ShiftVT =
N->getOperand(1).getValueType();
6616 unsigned VShiftOpc =
6618 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6623 EVT VT =
N->getValueType(0);
6632 "Unknown shift to lower!");
6634 unsigned ShOpc =
N->getOpcode();
6635 if (ST->hasMVEIntegerOps()) {
6665 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6679 if (ST->isThumb1Only())
6684 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6700 bool Invert =
false;
6707 EVT VT =
Op.getValueType();
6715 assert(ST->hasMVEIntegerOps() &&
6716 "No hardware support for integer vector comparison!");
6718 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6741 Merged = DAG.
getNode(ISD::BITCAST, dl, CmpVT, Merged);
6743 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6753 switch (SetCCOpcode) {
6757 if (ST->hasMVEFloatOps()) {
6760 Invert =
true; [[fallthrough]];
6765 case ISD::SETLT: Swap =
true; [[fallthrough]];
6769 case ISD::SETLE: Swap =
true; [[fallthrough]];
6785 Result = DAG.
getNOT(dl, Result, VT);
6788 case ISD::SETUO: Invert =
true; [[fallthrough]];
6797 Result = DAG.
getNOT(dl, Result, VT);
6803 switch (SetCCOpcode) {
6806 if (ST->hasMVEIntegerOps()) {
6809 Invert =
true; [[fallthrough]];
6812 case ISD::SETLT: Swap =
true; [[fallthrough]];
6814 case ISD::SETLE: Swap =
true; [[fallthrough]];
6831 if (AndOp.getNode() && AndOp.getOpcode() == ISD::BITCAST)
6834 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6835 Op0 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(0));
6836 Op1 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(1));
6839 Result = DAG.
getNOT(dl, Result, VT);
6873 Result = DAG.
getNOT(dl, Result, VT);
6885 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6912 unsigned OpCmode, Imm;
6923 switch (SplatBitSize) {
6928 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6931 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6936 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6937 if ((SplatBits & ~0xff) == 0) {
6943 if ((SplatBits & ~0xff00) == 0) {
6946 Imm = SplatBits >> 8;
6956 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6957 if ((SplatBits & ~0xff) == 0) {
6963 if ((SplatBits & ~0xff00) == 0) {
6966 Imm = SplatBits >> 8;
6969 if ((SplatBits & ~0xff0000) == 0) {
6972 Imm = SplatBits >> 16;
6975 if ((SplatBits & ~0xff000000) == 0) {
6978 Imm = SplatBits >> 24;
6985 if ((SplatBits & ~0xffff) == 0 &&
6986 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6989 Imm = SplatBits >> 8;
6997 if ((SplatBits & ~0xffffff) == 0 &&
6998 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
7001 Imm = SplatBits >> 16;
7017 unsigned ImmMask = 1;
7019 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
7020 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
7022 }
else if ((SplatBits & BitMask) != 0) {
7031 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
7045 EVT VT =
Op.getValueType();
7046 bool IsDouble = (VT == MVT::f64);
7052 if (
ST->genExecuteOnly()) {
7054 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
7055 "Unexpected architecture");
7078 if (!
ST->hasVFP3Base())
7083 if (IsDouble && !Subtarget->hasFP64())
7090 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7108 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7117 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7128 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
7145 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
7171 unsigned ExpectedElt = Imm;
7172 for (
unsigned i = 1; i < NumElts; ++i) {
7176 if (ExpectedElt == NumElts)
7179 if (M[i] < 0)
continue;
7180 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7188 bool &ReverseVEXT,
unsigned &Imm) {
7190 ReverseVEXT =
false;
7201 unsigned ExpectedElt = Imm;
7202 for (
unsigned i = 1; i < NumElts; ++i) {
7206 if (ExpectedElt == NumElts * 2) {
7211 if (M[i] < 0)
continue;
7212 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7227 return VT == MVT::v8i8 && M.size() == 8;
7232 if (Mask.size() == Elements * 2)
7233 return Index / Elements;
7234 return Mask[Index] == 0 ? 0 : 1;
7264 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7272 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7274 for (
unsigned j = 0; j < NumElts; j += 2) {
7275 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7276 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7281 if (M.size() == NumElts*2)
7296 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7299 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7301 for (
unsigned j = 0; j < NumElts; j += 2) {
7302 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7303 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7308 if (M.size() == NumElts*2)
7328 if (M.size() != NumElts && M.size() != NumElts*2)
7331 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7333 for (
unsigned j = 0; j < NumElts; ++j) {
7334 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7339 if (M.size() == NumElts*2)
7358 if (M.size() != NumElts && M.size() != NumElts*2)
7361 unsigned Half = NumElts / 2;
7362 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7364 for (
unsigned j = 0; j < NumElts; j += Half) {
7365 unsigned Idx = WhichResult;
7366 for (
unsigned k = 0; k < Half; ++k) {
7367 int MIdx = M[i + j + k];
7368 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7375 if (M.size() == NumElts*2)
7399 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7402 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7404 unsigned Idx = WhichResult * NumElts / 2;
7405 for (
unsigned j = 0; j < NumElts; j += 2) {
7406 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7407 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7413 if (M.size() == NumElts*2)
7432 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7435 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7437 unsigned Idx = WhichResult * NumElts / 2;
7438 for (
unsigned j = 0; j < NumElts; j += 2) {
7439 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7440 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7446 if (M.size() == NumElts*2)
7459 unsigned &WhichResult,
7462 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7464 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7466 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7484 if (NumElts != M.size())
7488 for (
unsigned i = 0; i != NumElts; ++i)
7489 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7498 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7506 int Ofs = Top ? 1 : 0;
7507 int Upper = SingleSource ? 0 : NumElts;
7508 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7509 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7511 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7520 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7529 unsigned Offset = Top ? 0 : 1;
7530 unsigned N = SingleSource ? 0 : NumElts;
7531 for (
unsigned i = 0; i < NumElts; i += 2) {
7532 if (M[i] >= 0 && M[i] != (
int)i)
7534 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7543 if (NumElts != M.size())
7551 unsigned Off0 = rev ? NumElts / 2 : 0;
7552 unsigned Off1 = rev ? 0 : NumElts / 2;
7553 for (
unsigned i = 0; i < NumElts; i += 2) {
7554 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7556 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7572 if (!ST->hasMVEFloatOps())
7577 if (VT != MVT::v8f16)
7598 for (
unsigned i = 1; i < 4; i++) {
7625 if (!ST->hasMVEFloatOps())
7630 if (VT != MVT::v4f32)
7646 for (
unsigned i = 1; i < 4; i++) {
7648 return Trunc.
getOpcode() == ISD::FP_EXTEND &&
7669 Val =
N->getAsZExtVal();
7671 if (ST->isThumb1Only()) {
7672 if (Val <= 255 || ~Val <= 255)
7684 EVT VT =
Op.getValueType();
7686 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7690 unsigned BitsPerBool;
7694 }
else if (NumElts == 4) {
7697 }
else if (NumElts == 8) {
7700 }
else if (NumElts == 16) {
7711 return U.get().isUndef() || U.get() == FirstOp;
7719 unsigned Bits32 = 0;
7720 for (
unsigned i = 0; i < NumElts; ++i) {
7724 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7726 Bits32 |= BoolMask << (i * BitsPerBool);
7732 for (
unsigned i = 0; i < NumElts; ++i) {
7745 if (!ST->hasMVEIntegerOps())
7749 EVT VT =
Op.getValueType();
7759 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7763 for (
unsigned I = 2;
I < NumElts;
I++) {
7779 switch (
N->getOpcode()) {
7790 return N->getOperand(1).getNode() ==
Op;
7792 switch (
N->getConstantOperandVal(0)) {
7793 case Intrinsic::arm_mve_add_predicated:
7794 case Intrinsic::arm_mve_mul_predicated:
7795 case Intrinsic::arm_mve_qadd_predicated:
7796 case Intrinsic::arm_mve_vhadd:
7797 case Intrinsic::arm_mve_hadd_predicated:
7798 case Intrinsic::arm_mve_vqdmulh:
7799 case Intrinsic::arm_mve_qdmulh_predicated:
7800 case Intrinsic::arm_mve_vqrdmulh:
7801 case Intrinsic::arm_mve_qrdmulh_predicated:
7802 case Intrinsic::arm_mve_vqdmull:
7803 case Intrinsic::arm_mve_vqdmull_predicated:
7805 case Intrinsic::arm_mve_sub_predicated:
7806 case Intrinsic::arm_mve_qsub_predicated:
7807 case Intrinsic::arm_mve_vhsub:
7808 case Intrinsic::arm_mve_hsub_predicated:
7809 return N->getOperand(2).getNode() ==
Op;
7824 EVT VT =
Op.getValueType();
7832 APInt SplatBits, SplatUndef;
7833 unsigned SplatBitSize;
7835 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7842 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7844 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7845 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7846 : SplatBitSize == 16 ? MVT::v8i16
7853 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7854 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7859 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7867 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7869 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7877 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7887 if (
ST->hasMVEIntegerOps() &&
7888 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7889 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7890 : SplatBitSize == 16 ? MVT::v8i16
7907 bool isOnlyLowElement =
true;
7908 bool usesOnlyOneValue =
true;
7909 bool hasDominantValue =
false;
7914 DenseMap<SDValue, unsigned> ValueCounts;
7916 for (
unsigned i = 0; i < NumElts; ++i) {
7921 isOnlyLowElement =
false;
7925 unsigned &
Count = ValueCounts[
V];
7928 if (++
Count > (NumElts / 2)) {
7929 hasDominantValue =
true;
7933 if (ValueCounts.
size() != 1)
7934 usesOnlyOneValue =
false;
7935 if (!
Value.getNode() && !ValueCounts.
empty())
7938 if (ValueCounts.
empty())
7950 if (hasDominantValue && EltSize <= 32) {
7959 ConstantSDNode *constIndex;
7966 if (VT !=
Value->getOperand(0).getValueType()) {
7979 if (!usesOnlyOneValue) {
7982 for (
unsigned I = 0;
I < NumElts; ++
I) {
7987 Ops.push_back(
Op.getOperand(
I));
7997 assert(FVT == MVT::f32 || FVT == MVT::f16);
7998 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7999 for (
unsigned i = 0; i < NumElts; ++i)
8000 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, IVT,
8004 Val = LowerBUILD_VECTOR(Val, DAG, ST);
8006 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8008 if (usesOnlyOneValue) {
8035 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
8055 if (EltSize >= 32) {
8061 for (
unsigned i = 0; i < NumElts; ++i)
8062 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, EltVT,
Op.getOperand(i)));
8064 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8075 for (
unsigned i = 0 ; i < NumElts; ++i) {
8094 EVT VT =
Op.getValueType();
8097 struct ShuffleSourceInfo {
8099 unsigned MinElt = std::numeric_limits<unsigned>::max();
8100 unsigned MaxElt = 0;
8110 int WindowScale = 1;
8112 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8120 for (
unsigned i = 0; i < NumElts; ++i) {
8135 SDValue SourceVec =
V.getOperand(0);
8137 if (Source == Sources.
end())
8141 unsigned EltNo =
V.getConstantOperandVal(1);
8148 if (Sources.
size() > 2)
8154 for (
auto &Source : Sources) {
8155 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8156 if (SrcEltTy.
bitsLT(SmallestEltTy))
8157 SmallestEltTy = SrcEltTy;
8159 unsigned ResMultiplier =
8167 for (
auto &Src : Sources) {
8168 EVT SrcVT = Src.ShuffleVec.getValueType();
8172 if (SrcVTSize == VTSize)
8181 if (SrcVTSize < VTSize) {
8182 if (2 * SrcVTSize != VTSize)
8188 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8192 if (SrcVTSize != 2 * VTSize)
8195 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8200 if (Src.MinElt >= NumSrcElts) {
8205 Src.WindowBase = -NumSrcElts;
8206 }
else if (Src.MaxElt < NumSrcElts) {
8223 Src.WindowBase = -Src.MinElt;
8230 for (
auto &Src : Sources) {
8231 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8232 if (SrcEltTy == SmallestEltTy)
8237 Src.WindowBase *= Src.WindowScale;
8242 for (
auto Src : Sources)
8243 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8251 if (
Entry.isUndef())
8260 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8263 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8267 int *LaneMask = &
Mask[i * ResMultiplier];
8269 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8270 ExtractBase += NumElts * (Src - Sources.begin());
8271 for (
int j = 0;
j < LanesDefined; ++
j)
8272 LaneMask[j] = ExtractBase + j;
8278 assert(Sources.size() <= 2 &&
"Too many sources!");
8281 for (
unsigned i = 0; i < Sources.size(); ++i)
8310 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8330 unsigned PFIndexes[4];
8331 for (
unsigned i = 0; i != 4; ++i) {
8335 PFIndexes[i] = M[i];
8339 unsigned PFTableIndex =
8340 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8342 unsigned Cost = (PFEntry >> 30);
8348 bool ReverseVEXT, isV_UNDEF;
8349 unsigned Imm, WhichResult;
8352 if (EltSize >= 32 ||
8359 else if (Subtarget->hasNEON() &&
8364 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8367 else if (Subtarget->hasMVEIntegerOps() &&
8371 else if (Subtarget->hasMVEIntegerOps() &&
8385 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8386 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8387 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8390 if (LHSID == (1*9+2)*9+3)
return LHS;
8391 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8448 for (
int I : ShuffleMask)
8461 EVT VT =
Op.getValueType();
8463 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8464 "Expect an v8i16/v16i8 type");
8470 std::vector<int> NewMask;
8474 NewMask.push_back(i);
8514 if (VT != MVT::v16i1)
8525 return DAG.
getNode(ISD::BITCAST, dl, NewVT, PredAsVector);
8530 EVT VT =
Op.getValueType();
8534 assert(ST->hasMVEIntegerOps() &&
8535 "No support for vector shuffle of boolean predicates");
8561 "Expected identical vector type in expanded i1 shuffle!");
8565 PredAsVector2, ShuffleMask);
8570 if (VT == MVT::v2i1) {
8587 EVT VT =
Op.getValueType();
8591 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8592 "Unexpected vector type");
8594 int QuarterSize = NumElts / 4;
8603 for (
int i = 0; i <
Length; i++) {
8604 if (ShuffleMask[Start + i] >= 0) {
8605 if (ShuffleMask[Start + i] %
Length != i)
8607 MovIdx = ShuffleMask[Start + i] /
Length;
8615 for (
int i = 1; i <
Length; i++) {
8616 if (ShuffleMask[Start + i] >= 0 &&
8617 (ShuffleMask[Start + i] /
Length != MovIdx ||
8618 ShuffleMask[Start + i] %
Length != i))
8624 for (
int Part = 0; Part < 4; ++Part) {
8626 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8640 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8645 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8647 for (
int Part = 0; Part < 4; ++Part)
8648 for (
int i = 0; i < QuarterSize; i++)
8650 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8652 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8655 for (
int Part = 0; Part < 4; ++Part)
8671 EVT VT =
Op.getValueType();
8683 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8687 if (Mask[i] != i + BaseOffset) {
8688 if (OffElement == -1)
8694 return NonUndef > 2 && OffElement != -1;
8698 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8700 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8711 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8722 EVT VT =
Op.getValueType();
8726 if (ST->hasMVEIntegerOps() && EltSize == 1)
8737 if (EltSize <= 32) {
8741 if (Lane == -1) Lane = 0;
8752 bool IsScalarToVector =
true;
8755 IsScalarToVector =
false;
8758 if (IsScalarToVector)
8765 bool ReverseVEXT =
false;
8767 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8791 unsigned WhichResult = 0;
8792 bool isV_UNDEF =
false;
8793 if (ST->hasNEON()) {
8795 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8802 if (ST->hasMVEIntegerOps()) {
8837 }) &&
"Unexpected shuffle index into UNDEF operand!");
8840 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8843 assert((WhichResult == 0) &&
8844 "In-place shuffle of concat can only have one result!");
8853 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8857 for (
bool Top : {
false,
true}) {
8858 for (
bool SingleSource : {
false,
true}) {
8859 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8864 SingleSource ? V1 : V2);
8880 unsigned PFIndexes[4];
8881 for (
unsigned i = 0; i != 4; ++i) {
8882 if (ShuffleMask[i] < 0)
8885 PFIndexes[i] = ShuffleMask[i];
8889 unsigned PFTableIndex =
8890 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8892 unsigned Cost = (PFEntry >> 30);
8898 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8899 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8909 if (EltSize >= 32) {
8914 V1 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V1);
8915 V2 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V2);
8917 for (
unsigned i = 0; i < NumElts; ++i) {
8918 if (ShuffleMask[i] < 0)
8922 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8927 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8930 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8934 if (ST->hasNEON() && VT == MVT::v8i8)
8938 if (ST->hasMVEIntegerOps())
8947 EVT VecVT =
Op.getOperand(0).getValueType();
8950 assert(ST->hasMVEIntegerOps() &&
8951 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8955 unsigned Lane =
Op.getConstantOperandVal(2);
8956 unsigned LaneWidth =
8958 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8976 if (Subtarget->hasMVEIntegerOps() &&
8977 Op.getValueType().getScalarSizeInBits() == 1)
9001 IVecIn, IElt, Lane);
9002 return DAG.
getNode(ISD::BITCAST, dl, VecVT, IVecOut);
9010 EVT VecVT =
Op.getOperand(0).getValueType();
9013 assert(ST->hasMVEIntegerOps() &&
9014 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9018 unsigned Lane =
Op.getConstantOperandVal(1);
9019 unsigned LaneWidth =
9050 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
9051 "Unexpected custom CONCAT_VECTORS lowering");
9053 "Unexpected custom CONCAT_VECTORS lowering");
9054 assert(ST->hasMVEIntegerOps() &&
9055 "CONCAT_VECTORS lowering only supported for MVE");
9059 EVT Op2VT = V2.getValueType();
9060 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9061 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9062 "Unexpected i1 concat operations!");
9075 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9089 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9090 EVT NewVT = NewV.getValueType();
9091 EVT ConcatVT = ConVec.getValueType();
9092 unsigned ExtScale = 1;
9093 if (NewVT == MVT::v2f64) {
9107 ConVec = ExtractInto(NewV1, ConVec, j);
9108 ConVec = ExtractInto(NewV2, ConVec, j);
9118 while (ConcatOps.
size() > 1) {
9119 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
9122 ConcatOps[
I / 2] = ConcatPair(V1, V2);
9126 return ConcatOps[0];
9131 EVT VT =
Op->getValueType(0);
9137 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9138 "unexpected CONCAT_VECTORS");
9145 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op0),
9149 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op1),
9151 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Val);
9159 EVT VT =
Op.getValueType();
9165 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9166 assert(ST->hasMVEIntegerOps() &&
9167 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9177 EVT SubVT = MVT::v4i32;
9179 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9194 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9210 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9211 EVT VT =
N->getValueType(0);
9212 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9213 "Expected a vector i1 type!");
9215 EVT FromVT =
Op.getValueType();
9226 if (!Subtarget->hasMVEIntegerOps())
9229 EVT ToVT =
N->getValueType(0);
9272 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9274 EVT FromVT =
N->getOperand(0).getValueType();
9275 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9286 if (!Subtarget->hasMVEIntegerOps())
9291 EVT ToVT =
N->getValueType(0);
9292 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9295 EVT FromVT =
Op.getValueType();
9296 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9307 SDValue Ext1 = Ext.getValue(1);
9310 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9311 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9323 EVT VT =
N->getValueType(0);
9324 if (VT == MVT::v2i64 &&
N->getOpcode() == ISD::BITCAST) {
9325 SDNode *BVN =
N->getOperand(0).getNode();
9330 unsigned HiElt = 1 - LoElt;
9335 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9351 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9352 SDNode *Elt =
N->getOperand(i).getNode();
9355 unsigned HalfSize = EltSize / 2;
9357 if (!
isIntN(HalfSize,
C->getSExtValue()))
9360 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9399 switch (OrigSimpleTy) {
9415 unsigned ExtOpcode) {
9438 if (ExtendedTy == LD->getMemoryVT())
9439 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9440 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9441 LD->getMemOperand()->getFlags());
9447 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9448 LD->getMemoryVT(), LD->getAlign(),
9449 LD->getMemOperand()->getFlags());
9462 N->getOperand(0)->getValueType(0),
9468 "Expected extending load");
9474 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9482 if (
N->getOpcode() == ISD::BITCAST) {
9483 SDNode *BVN =
N->getOperand(0).getNode();
9485 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9493 EVT VT =
N->getValueType(0);
9499 for (
unsigned i = 0; i != NumElts; ++i) {
9500 const APInt &CInt =
N->getConstantOperandAPInt(i);
9509 unsigned Opcode =
N->getOpcode();
9511 SDNode *N0 =
N->getOperand(0).getNode();
9512 SDNode *N1 =
N->getOperand(1).getNode();
9520 unsigned Opcode =
N->getOpcode();
9522 SDNode *N0 =
N->getOperand(0).getNode();
9523 SDNode *N1 =
N->getOperand(1).getNode();
9533 EVT VT =
Op.getValueType();
9535 "unexpected type for custom-lowering ISD::MUL");
9536 SDNode *N0 =
Op.getOperand(0).getNode();
9537 SDNode *N1 =
Op.getOperand(1).getNode();
9538 unsigned NewOpc = 0;
9542 if (isN0SExt && isN1SExt)
9547 if (isN0ZExt && isN1ZExt)
9549 else if (isN1SExt || isN1ZExt) {
9566 if (VT == MVT::v2i64)
9583 "unexpected types for extended operands to VMULL");
9584 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9600 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N00), Op1),
9602 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N01), Op1));
9619 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9626 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32,
X);
9629 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32,
X);
9653 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9656 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9664 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9667 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9677 EVT VT =
Op.getValueType();
9678 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9679 "unexpected type for custom-lowering ISD::SDIV");
9686 if (VT == MVT::v8i8) {
9714 EVT VT =
Op.getValueType();
9715 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9716 "unexpected type for custom-lowering ISD::UDIV");
9723 if (VT == MVT::v8i8) {
9762 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9765 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9769 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9777 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9780 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9790 EVT VT =
N->getValueType(0);
9804 Op.getOperand(1), Carry);
9818 Op.getOperand(1), Carry);
9833 assert(Subtarget->isTargetDarwin());
9852 if (ShouldUseSRet) {
9854 const uint64_t ByteSize =
DL.getTypeAllocSize(RetTy);
9855 const Align StackAlign =
DL.getPrefTypeAlign(RetTy);
9860 Entry.IsSExt =
false;
9861 Entry.IsZExt =
false;
9862 Entry.IsSRet =
true;
9863 Args.push_back(Entry);
9867 Args.emplace_back(Arg, ArgTy);
9870 (ArgVT == MVT::f64) ? RTLIB::SINCOS_STRET_F64 : RTLIB::SINCOS_STRET_F32;
9875 TargetLowering::CallLoweringInfo CLI(DAG);
9878 .
setCallee(CC, RetTy, Callee, std::move(Args))
9880 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
9883 return CallResult.first;
9886 DAG.
getLoad(ArgVT, dl, CallResult.second, SRet, MachinePointerInfo());
9894 SDVTList Tys = DAG.
getVTList(ArgVT, ArgVT);
9902 EVT VT =
Op.getValueType();
9903 assert((VT == MVT::i32 || VT == MVT::i64) &&
9904 "unexpected type for custom lowering DIV");
9910 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9912 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9919 for (
auto AI : {1, 0}) {
9921 Args.emplace_back(Operand,
9929 ES, std::move(Args));
9939ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9947 const bool MinSize =
ST.hasMinSize();
9948 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9949 :
ST.hasDivideInARMMode();
9953 if (
N->getOperand(0).getValueType().isVector())
9958 if (!(MinSize && HasDivide))
9971 if (Divisor.
sgt(128))
9979 assert(
Op.getValueType() == MVT::i32 &&
9980 "unexpected type for custom lowering DIV");
9986 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9992 if (
N->getValueType(0) == MVT::i32)
10000void ARMTargetLowering::ExpandDIV_Windows(
10005 assert(
Op.getValueType() == MVT::i64 &&
10006 "unexpected type for custom lowering DIV");
10023 EVT MemVT = LD->getMemoryVT();
10024 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10025 MemVT == MVT::v16i1) &&
10026 "Expected a predicate type!");
10027 assert(MemVT ==
Op.getValueType());
10029 "Expected a non-extending load");
10030 assert(LD->isUnindexed() &&
"Expected a unindexed load");
10044 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
10046 LD->getMemOperand());
10053 if (MemVT != MVT::v16i1)
10062 EVT MemVT =
LD->getMemoryVT();
10063 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10065 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10066 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
10067 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10071 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10081 EVT MemVT = ST->getMemoryVT();
10082 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10083 MemVT == MVT::v16i1) &&
10084 "Expected a predicate type!");
10085 assert(MemVT == ST->getValue().getValueType());
10086 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10087 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10092 SDValue Build = ST->getValue();
10093 if (MemVT != MVT::v16i1) {
10112 ST->getChain(), dl, GRP, ST->getBasePtr(),
10114 ST->getMemOperand());
10120 EVT MemVT = ST->getMemoryVT();
10121 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10123 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10139 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10140 MemVT, ST->getMemOperand());
10141 }
else if (Subtarget->hasMVEIntegerOps() &&
10142 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10143 MemVT == MVT::v16i1))) {
10158 MVT VT =
Op.getSimpleValueType();
10160 SDValue PassThru =
N->getPassThru();
10171 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10172 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10173 N->getExtensionType(),
N->isExpandingLoad());
10175 bool PassThruIsCastZero = (PassThru.
getOpcode() == ISD::BITCAST ||
10178 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10185 if (!ST->hasMVEIntegerOps())
10189 unsigned BaseOpcode = 0;
10190 switch (
Op->getOpcode()) {
10192 case ISD::VECREDUCE_FADD: BaseOpcode =
ISD::FADD;
break;
10193 case ISD::VECREDUCE_FMUL: BaseOpcode =
ISD::FMUL;
break;
10194 case ISD::VECREDUCE_MUL: BaseOpcode =
ISD::MUL;
break;
10195 case ISD::VECREDUCE_AND: BaseOpcode =
ISD::AND;
break;
10196 case ISD::VECREDUCE_OR: BaseOpcode =
ISD::OR;
break;
10197 case ISD::VECREDUCE_XOR: BaseOpcode =
ISD::XOR;
break;
10198 case ISD::VECREDUCE_FMAX: BaseOpcode = ISD::FMAXNUM;
break;
10199 case ISD::VECREDUCE_FMIN: BaseOpcode = ISD::FMINNUM;
break;
10206 unsigned NumActiveLanes = NumElts;
10208 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10209 NumActiveLanes == 2) &&
10210 "Only expected a power 2 vector size");
10214 while (NumActiveLanes > 4) {
10217 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10218 NumActiveLanes /= 2;
10222 if (NumActiveLanes == 4) {
10232 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10233 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10234 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10240 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10244 if (EltVT !=
Op->getValueType(0))
10251 if (!ST->hasMVEFloatOps())
10258 if (!ST->hasNEON())
10266 unsigned PairwiseIntrinsic = 0;
10267 switch (
Op->getOpcode()) {
10270 case ISD::VECREDUCE_UMIN:
10271 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10273 case ISD::VECREDUCE_UMAX:
10274 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10276 case ISD::VECREDUCE_SMIN:
10277 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10279 case ISD::VECREDUCE_SMAX:
10280 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10286 unsigned NumActiveLanes = NumElts;
10288 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10289 NumActiveLanes == 2) &&
10290 "Only expected a power 2 vector size");
10296 VT =
Lo.getValueType();
10298 NumActiveLanes /= 2;
10302 while (NumActiveLanes > 1) {
10304 NumActiveLanes /= 2;
10311 if (EltVT !=
Op.getValueType()) {
10312 unsigned Extend = 0;
10313 switch (
Op->getOpcode()) {
10316 case ISD::VECREDUCE_UMIN:
10317 case ISD::VECREDUCE_UMAX:
10320 case ISD::VECREDUCE_SMIN:
10321 case ISD::VECREDUCE_SMAX:
10325 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10370 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10376 SDLoc dl(V.getNode());
10377 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10387 assert(
N->getValueType(0) == MVT::i64 &&
10388 "AtomicCmpSwap on types less than 64 should be legal");
10397 ARM::CMP_SWAP_64,
SDLoc(
N),
10398 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10417 EVT VT =
Op.getValueType();
10426 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10428 Chain, IsSignaling);
10429 if (!
RHS.getNode()) {
10445 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10447 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10448 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10465 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10468 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10481 if (!IsSigned && Subtarget->isThumb1Only()) {
10499 Sub1Result, Sub1Result, Flags1);
10514 if (
Op.getValueType() != MVT::i32)
10537 bool CanUseAdd =
false;
10578 GTCondValue, Flags);
10583 LTCondValue, Flags);
10585 if (
Op.getValueType() != MVT::i32)
10593 switch (
Op.getOpcode()) {
10602 case ISD::BRCOND:
return LowerBRCOND(
Op, DAG);
10603 case ISD::BR_CC:
return LowerBR_CC(
Op, DAG);
10604 case ISD::BR_JT:
return LowerBR_JT(
Op, DAG);
10625 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10629 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10630 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10650 case ISD::SET_ROUNDING:
return LowerSET_ROUNDING(
Op, DAG);
10651 case ISD::SET_FPMODE:
10652 return LowerSET_FPMODE(
Op, DAG);
10653 case ISD::RESET_FPMODE:
10654 return LowerRESET_FPMODE(
Op, DAG);
10657 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10658 return LowerDIV_Windows(
Op, DAG,
true);
10661 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10662 return LowerDIV_Windows(
Op, DAG,
false);
10669 return LowerSignedALUO(
Op, DAG);
10672 return LowerUnsignedALUO(
Op, DAG);
10684 case ISD::VECREDUCE_MUL:
10685 case ISD::VECREDUCE_AND:
10686 case ISD::VECREDUCE_OR:
10687 case ISD::VECREDUCE_XOR:
10689 case ISD::VECREDUCE_FADD:
10690 case ISD::VECREDUCE_FMUL:
10691 case ISD::VECREDUCE_FMIN:
10692 case ISD::VECREDUCE_FMAX:
10694 case ISD::VECREDUCE_UMIN:
10695 case ISD::VECREDUCE_UMAX:
10696 case ISD::VECREDUCE_SMIN:
10697 case ISD::VECREDUCE_SMAX:
10699 case ISD::ATOMIC_LOAD:
10701 case ISD::FSINCOS:
return LowerFSINCOS(
Op, DAG);
10704 case ISD::DYNAMIC_STACKALLOC:
10705 if (Subtarget->isTargetWindows())
10706 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10711 case ISD::FP_EXTEND:
return LowerFP_EXTEND(
Op, DAG);
10715 return LowerSPONENTRY(
Op, DAG);
10716 case ISD::FP_TO_BF16:
10717 return LowerFP_TO_BF16(
Op, DAG);
10721 return LowerCMP(
Op, DAG);
10723 return LowerABS(
Op, DAG);
10729 unsigned IntNo =
N->getConstantOperandVal(0);
10731 if (IntNo == Intrinsic::arm_smlald)
10733 else if (IntNo == Intrinsic::arm_smlaldx)
10735 else if (IntNo == Intrinsic::arm_smlsld)
10737 else if (IntNo == Intrinsic::arm_smlsldx)
10744 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10748 N->getOperand(1),
N->getOperand(2),
10760 switch (
N->getOpcode()) {
10767 Res = ExpandBITCAST(
N, DAG, Subtarget);
10776 Res = LowerREM(
N, DAG);
10780 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10791 case ISD::READCYCLECOUNTER:
10796 assert(Subtarget->isTargetWindows() &&
"can only expand DIV on Windows");
10799 case ISD::ATOMIC_CMP_SWAP:
10834 "ROPI/RWPI not currently supported with SjLj");
10843 bool isThumb = Subtarget->isThumb();
10844 bool isThumb2 = Subtarget->
isThumb2();
10847 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10853 : &ARM::GPRRegClass;
10871 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10877 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10883 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10901 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10906 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10911 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10916 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10922 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10937 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10943 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10959 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10966 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10967 : &ARM::GPRnopcRegClass;
10971 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10972 unsigned MaxCSNum = 0;
10973 for (MachineBasicBlock &BB : *MF) {
10979 for (MachineInstr &
II : BB) {
10980 if (!
II.isEHLabel())
10983 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10984 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10986 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10987 for (
unsigned Idx : CallSiteIdxs) {
10988 CallSiteNumToLPad[Idx].push_back(&BB);
10989 MaxCSNum = std::max(MaxCSNum, Idx);
10996 std::vector<MachineBasicBlock*> LPadList;
10997 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10998 LPadList.reserve(CallSiteNumToLPad.
size());
10999 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
11000 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
11001 for (MachineBasicBlock *
MBB : MBBList) {
11002 LPadList.push_back(
MBB);
11007 assert(!LPadList.empty() &&
11008 "No landing pad destinations for the dispatch jump table!");
11011 MachineJumpTableInfo *JTI =
11018 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
11021 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
11023 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
11026 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
11030 MF->insert(MF->end(), DispatchBB);
11031 MF->insert(MF->end(), DispContBB);
11032 MF->insert(MF->end(), TrapBB);
11036 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11038 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
11042 MachineInstrBuilder MIB;
11043 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11045 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
11055 unsigned NumLPads = LPadList.size();
11056 if (Subtarget->isThumb2()) {
11057 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11058 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11064 if (NumLPads < 256) {
11065 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11067 .
addImm(LPadList.size())
11070 Register VReg1 =
MRI->createVirtualRegister(TRC);
11071 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11072 .
addImm(NumLPads & 0xFFFF)
11075 unsigned VReg2 = VReg1;
11076 if ((NumLPads & 0xFFFF0000) != 0) {
11077 VReg2 =
MRI->createVirtualRegister(TRC);
11078 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11084 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11090 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11095 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11096 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11100 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11101 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11108 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11112 }
else if (Subtarget->isThumb()) {
11113 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11114 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11120 if (NumLPads < 256) {
11121 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11126 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11131 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11132 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11134 Register VReg1 =
MRI->createVirtualRegister(TRC);
11135 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11139 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11145 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11150 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
11151 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11157 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11158 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11162 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11163 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11169 MachineMemOperand *JTMMOLd =
11173 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11174 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11180 unsigned NewVReg6 = NewVReg5;
11181 if (IsPositionIndependent) {
11182 NewVReg6 =
MRI->createVirtualRegister(TRC);
11183 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11190 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11194 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11195 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11201 if (NumLPads < 256) {
11202 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11206 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11207 Register VReg1 =
MRI->createVirtualRegister(TRC);
11208 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11209 .
addImm(NumLPads & 0xFFFF)
11212 unsigned VReg2 = VReg1;
11213 if ((NumLPads & 0xFFFF0000) != 0) {
11214 VReg2 =
MRI->createVirtualRegister(TRC);
11215 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11221 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11226 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11231 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11232 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11234 Register VReg1 =
MRI->createVirtualRegister(TRC);
11235 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11240 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11251 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11252 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11257 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11258 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11262 MachineMemOperand *JTMMOLd =
11265 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11266 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11273 if (IsPositionIndependent) {
11274 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11279 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11286 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11287 for (MachineBasicBlock *CurMBB : LPadList) {
11288 if (SeenMBBs.
insert(CurMBB).second)
11295 for (MachineBasicBlock *BB : InvokeBBs) {
11299 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11300 while (!Successors.empty()) {
11301 MachineBasicBlock *SMBB = Successors.pop_back_val();
11303 BB->removeSuccessor(SMBB);
11309 BB->normalizeSuccProbs();
11316 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11317 if (!
II->isCall())
continue;
11319 DenseSet<unsigned> DefRegs;
11321 OI =
II->operands_begin(), OE =
II->operands_end();
11323 if (!OI->isReg())
continue;
11324 DefRegs.
insert(OI->getReg());
11327 MachineInstrBuilder MIB(*MF, &*
II);
11329 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11330 unsigned Reg = SavedRegs[i];
11331 if (Subtarget->isThumb2() &&
11332 !ARM::tGPRRegClass.contains(
Reg) &&
11333 !ARM::hGPRRegClass.contains(
Reg))
11335 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11337 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11349 for (MachineBasicBlock *MBBLPad : MBBLPads)
11350 MBBLPad->setIsEHPad(
false);
11353 MI.eraseFromParent();
11366static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11368 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11369 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11371 return LdSize == 4 ? ARM::tLDRi
11372 : LdSize == 2 ? ARM::tLDRHi
11373 : LdSize == 1 ? ARM::tLDRBi : 0;
11375 return LdSize == 4 ? ARM::t2LDR_POST
11376 : LdSize == 2 ? ARM::t2LDRH_POST
11377 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11378 return LdSize == 4 ? ARM::LDR_POST_IMM
11379 : LdSize == 2 ? ARM::LDRH_POST
11380 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11385static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11387 return StSize == 16 ? ARM::VST1q32wb_fixed
11388 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11390 return StSize == 4 ? ARM::tSTRi
11391 : StSize == 2 ? ARM::tSTRHi
11392 : StSize == 1 ? ARM::tSTRBi : 0;
11394 return StSize == 4 ? ARM::t2STR_POST
11395 : StSize == 2 ? ARM::t2STRH_POST
11396 : StSize == 1 ? ARM::t2STRB_POST : 0;
11397 return StSize == 4 ? ARM::STR_POST_IMM
11398 : StSize == 2 ? ARM::STRH_POST
11399 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11406 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11407 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11408 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11409 assert(LdOpc != 0 &&
"Should have a load opcode");
11416 }
else if (IsThumb1) {
11422 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11427 }
else if (IsThumb2) {
11447 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11448 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11449 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11450 assert(StOpc != 0 &&
"Should have a store opcode");
11452 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11457 }
else if (IsThumb1) {
11464 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11469 }
else if (IsThumb2) {
11470 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11476 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11491 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11497 unsigned SizeVal =
MI.getOperand(2).getImm();
11498 unsigned Alignment =
MI.getOperand(3).getImm();
11503 unsigned UnitSize = 0;
11504 const TargetRegisterClass *TRC =
nullptr;
11505 const TargetRegisterClass *VecTRC =
nullptr;
11507 bool IsThumb1 = Subtarget->isThumb1Only();
11508 bool IsThumb2 = Subtarget->isThumb2();
11509 bool IsThumb = Subtarget->isThumb();
11511 if (Alignment & 1) {
11513 }
else if (Alignment & 2) {
11518 Subtarget->hasNEON()) {
11519 if ((Alignment % 16 == 0) && SizeVal >= 16)
11521 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11530 bool IsNeon = UnitSize >= 8;
11531 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11533 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11534 : UnitSize == 8 ? &ARM::DPRRegClass
11537 unsigned BytesLeft = SizeVal % UnitSize;
11538 unsigned LoopSize = SizeVal - BytesLeft;
11540 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11544 unsigned srcIn = src;
11545 unsigned destIn = dest;
11546 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11547 Register srcOut =
MRI.createVirtualRegister(TRC);
11548 Register destOut =
MRI.createVirtualRegister(TRC);
11549 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11551 IsThumb1, IsThumb2);
11553 IsThumb1, IsThumb2);
11561 for (
unsigned i = 0; i < BytesLeft; i++) {
11562 Register srcOut =
MRI.createVirtualRegister(TRC);
11563 Register destOut =
MRI.createVirtualRegister(TRC);
11564 Register scratch =
MRI.createVirtualRegister(TRC);
11566 IsThumb1, IsThumb2);
11568 IsThumb1, IsThumb2);
11572 MI.eraseFromParent();
11598 MF->
insert(It, loopMBB);
11599 MF->
insert(It, exitMBB);
11602 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11612 Register varEnd =
MRI.createVirtualRegister(TRC);
11613 if (Subtarget->useMovt()) {
11614 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11617 }
else if (Subtarget->genExecuteOnly()) {
11618 assert(IsThumb &&
"Non-thumb expected to have used movt");
11627 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11628 MachineMemOperand *CPMMO =
11652 MachineBasicBlock *entryBB = BB;
11654 Register varLoop =
MRI.createVirtualRegister(TRC);
11655 Register varPhi =
MRI.createVirtualRegister(TRC);
11656 Register srcLoop =
MRI.createVirtualRegister(TRC);
11657 Register srcPhi =
MRI.createVirtualRegister(TRC);
11658 Register destLoop =
MRI.createVirtualRegister(TRC);
11659 Register destPhi =
MRI.createVirtualRegister(TRC);
11667 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11673 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11675 IsThumb1, IsThumb2);
11677 IsThumb1, IsThumb2);
11681 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11687 MachineInstrBuilder MIB =
11689 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11698 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11707 auto StartOfExit = exitMBB->
begin();
11711 unsigned srcIn = srcLoop;
11712 unsigned destIn = destLoop;
11713 for (
unsigned i = 0; i < BytesLeft; i++) {
11714 Register srcOut =
MRI.createVirtualRegister(TRC);
11715 Register destOut =
MRI.createVirtualRegister(TRC);
11716 Register scratch =
MRI.createVirtualRegister(TRC);
11717 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11718 IsThumb1, IsThumb2);
11719 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11720 IsThumb1, IsThumb2);
11725 MI.eraseFromParent();
11733 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11736 assert(Subtarget->isTargetWindows() &&
11737 "__chkstk is only supported on Windows");
11738 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11758 switch (TM.getCodeModel()) {
11800 MI.eraseFromParent();
11809 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11824 .
addReg(
MI.getOperand(0).getReg())
11832 MI.eraseFromParent();
11856 if (miI == BB->
end()) {
11858 if (Succ->isLiveIn(ARM::CPSR))
11864 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11876 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11877 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11883 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11884 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11890 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11891 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11894 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11895 .
addUse(TotalIterationsReg)
11902 return TotalIterationsReg;
11913 Register TotalIterationsReg,
bool IsMemcpy) {
11920 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11921 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11922 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11930 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11931 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11932 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11939 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11940 Register RemainingLoopIterationsReg =
11941 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11942 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11943 .
addUse(TotalIterationsReg)
11945 .
addUse(RemainingLoopIterationsReg)
11949 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11950 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11951 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11952 .
addUse(ElementCountReg)
11954 .
addUse(RemainingElementsReg)
11958 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11959 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11960 .
addUse(PredCounterPhiReg)
11965 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11966 .
addUse(PredCounterPhiReg)
11974 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11975 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11984 SrcValueReg = OpSrcReg;
11986 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11997 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11998 .
addUse(LoopCounterPhiReg)
12001 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
12002 .
addUse(RemainingLoopIterationsReg)
12015 bool isThumb2 = Subtarget->isThumb2();
12016 switch (
MI.getOpcode()) {
12023 case ARM::tLDR_postidx: {
12027 .
add(
MI.getOperand(2))
12028 .
add(
MI.getOperand(3))
12029 .
add(
MI.getOperand(4))
12030 .
add(
MI.getOperand(0))
12032 MI.eraseFromParent();
12036 case ARM::MVE_MEMCPYLOOPINST:
12037 case ARM::MVE_MEMSETLOOPINST: {
12067 Register OpDestReg =
MI.getOperand(0).getReg();
12068 Register OpSrcReg =
MI.getOperand(1).getReg();
12069 Register OpSizeReg =
MI.getOperand(2).getReg();
12089 if (TpExit == BB) {
12091 "block containing memcpy/memset Pseudo");
12104 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12106 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12109 Properties.resetNoPHIs();
12121 MI.eraseFromParent();
12131 case ARM::t2STR_preidx:
12132 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12134 case ARM::t2STRB_preidx:
12135 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12137 case ARM::t2STRH_preidx:
12138 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12141 case ARM::STRi_preidx:
12142 case ARM::STRBi_preidx: {
12143 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12144 : ARM::STRB_PRE_IMM;
12146 unsigned Offset =
MI.getOperand(4).getImm();
12154 .
add(
MI.getOperand(0))
12155 .
add(
MI.getOperand(1))
12156 .
add(
MI.getOperand(2))
12158 .
add(
MI.getOperand(5))
12159 .
add(
MI.getOperand(6))
12161 MI.eraseFromParent();
12164 case ARM::STRr_preidx:
12165 case ARM::STRBr_preidx:
12166 case ARM::STRH_preidx: {
12168 switch (
MI.getOpcode()) {
12170 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12171 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12172 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12177 MI.eraseFromParent();
12181 case ARM::tMOVCCr_pseudo: {
12199 F->insert(It, copy0MBB);
12200 F->insert(It, sinkMBB);
12203 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12209 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12225 .
addImm(
MI.getOperand(3).getImm())
12226 .
addReg(
MI.getOperand(4).getReg());
12241 .
addReg(
MI.getOperand(1).getReg())
12243 .
addReg(
MI.getOperand(2).getReg())
12246 MI.eraseFromParent();
12251 case ARM::BCCZi64: {
12257 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12262 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12266 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12272 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12276 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12286 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12295 MI.eraseFromParent();
12299 case ARM::Int_eh_sjlj_setjmp:
12300 case ARM::Int_eh_sjlj_setjmp_nofp:
12301 case ARM::tInt_eh_sjlj_setjmp:
12302 case ARM::t2Int_eh_sjlj_setjmp:
12303 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12306 case ARM::Int_eh_sjlj_setup_dispatch:
12307 EmitSjLjDispatchBlock(
MI, BB);
12309 case ARM::COPY_STRUCT_BYVAL_I32:
12311 return EmitStructByval(
MI, BB);
12312 case ARM::WIN__CHKSTK:
12313 return EmitLowered__chkstk(
MI, BB);
12314 case ARM::WIN__DBZCHK:
12315 return EmitLowered__dbzchk(
MI, BB);
12331 if (!
Node->hasAnyUseOfValue(0)) {
12332 MI.getOperand(0).setIsDead(
true);
12334 if (!
Node->hasAnyUseOfValue(1)) {
12335 MI.getOperand(1).setIsDead(
true);
12339 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12340 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12341 : &ARM::GPRRegClass);
12348 if (
MI.getOpcode() == ARM::MEMCPY) {
12369 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12370 &&
"converted opcode should be the same except for cc_out"
12371 " (and, on Thumb1, pred)");
12379 if (Subtarget->isThumb1Only()) {
12380 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12381 MI.addOperand(
MI.getOperand(1));
12382 MI.removeOperand(1);
12386 for (
unsigned i =
MI.getNumOperands(); i--;) {
12388 if (
op.isReg() &&
op.isUse()) {
12391 MI.tieOperands(DefIdx, i);
12399 ccOutIdx =
MCID->getNumOperands() - 1;
12401 ccOutIdx =
MCID->getNumOperands() - 1;
12405 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12406 assert(!NewOpc &&
"Optional cc_out operand required");
12411 bool definesCPSR =
false;
12412 bool deadCPSR =
false;
12413 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12417 definesCPSR =
true;
12420 MI.removeOperand(i);
12424 if (!definesCPSR) {
12425 assert(!NewOpc &&
"Optional cc_out operand required");
12428 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12430 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12431 "expect uninitialized optional cc_out operand");
12433 if (!Subtarget->isThumb1Only())
12469 switch (
N->getOpcode()) {
12470 default:
return false;
12472 CC =
N->getOperand(0);
12494 EVT VT =
N->getValueType(0);
12495 CC =
N->getOperand(0);
12542 EVT VT =
N->getValueType(0);
12545 bool SwapSelectOps;
12547 NonConstantVal, DAG))
12553 OtherOp, NonConstantVal);
12559 CCOp, TrueVal, FalseVal);
12583 if (
N->getOpcode() ==
ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12598 if (!
N->getValueType(0).is64BitVector())
12606 EVT VT =
N->getValueType(0);
12645 EVT VT =
N->getValueType(0);
12651 Opcode = Intrinsic::arm_neon_vpaddls;
12653 Opcode = Intrinsic::arm_neon_vpaddlu;
12681 EVT VT =
N->getValueType(0);
12696 unsigned nextIndex = 0;
12747 Ops.push_back(Vec);
12764 return DAG.
getNode(ExtOp, dl, VT, tmp);
12795 if (SRA.getOpcode() !=
ISD::SRA) {
12802 if (Const->getZExtValue() != 31)
12807 if (SRA.getOperand(0) !=
Mul)
12811 SDLoc dl(AddcNode);
12812 unsigned Opcode = 0;
12818 Op0 =
Mul.getOperand(0);
12819 Op1 =
Mul.getOperand(1);
12822 Op0 =
Mul.getOperand(0);
12823 Op1 =
Mul.getOperand(1).getOperand(0);
12826 Op0 =
Mul.getOperand(0).getOperand(0);
12827 Op1 =
Mul.getOperand(1);
12830 Op0 =
Mul->getOperand(0).getOperand(0);
12831 Op1 =
Mul->getOperand(1).getOperand(0);
12840 SDValue HiMLALResult(SMLAL.getNode(), 1);
12841 SDValue LoMLALResult(SMLAL.getNode(), 0);
12847 SDValue resNode(AddcNode, 0);
12876 "Expect an ADDE or SUBE");
12880 "ADDE node has the wrong inputs");
12899 "Expect ADDC with two result values. First: i32");
12919 bool IsLeftOperandMUL =
false;
12924 IsLeftOperandMUL =
true;
12935 SDValue *LowAddSub =
nullptr;
12938 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12941 if (IsLeftOperandMUL)
12942 HiAddSub = &AddeSubeOp1;
12944 HiAddSub = &AddeSubeOp0;
12949 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12950 LoMul = &AddcSubcOp0;
12951 LowAddSub = &AddcSubcOp1;
12953 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12954 LoMul = &AddcSubcOp1;
12955 LowAddSub = &AddcSubcOp0;
12963 if (AddcSubcNode == HiAddSub->getNode() ||
12979 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12984 Ops.push_back(*HiAddSub);
12993 return SDValue(AddeSubeNode, 0);
13000 Ops.push_back(*LowAddSub);
13001 Ops.push_back(*HiAddSub);
13014 return SDValue(AddeSubeNode, 0);
13026 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13035 SDNode *UmlalNode =
nullptr;
13074 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13079 SDNode* AddcNode =
N->getOperand(2).getNode();
13080 SDNode* AddeNode =
N->getOperand(3).getNode();
13088 {N->getOperand(0), N->getOperand(1),
13089 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13113 int32_t imm =
C->getSExtValue();
13114 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13119 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13134 int64_t imm =
C->getSExtValue();
13145 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13146 N->getOperand(0),
RHS,
N->getOperand(2));
13158 if (!Subtarget->hasMVEIntegerOps())
13171 SetCC =
N->getOperand(0);
13175 TrueVal =
N->getOperand(1);
13176 FalseVal =
N->getOperand(2);
13178 LHS =
N->getOperand(0);
13179 RHS =
N->getOperand(1);
13181 TrueVal =
N->getOperand(2);
13182 FalseVal =
N->getOperand(3);
13187 unsigned int Opcode = 0;
13188 if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMIN ||
13189 FalseVal->getOpcode() == ISD::VECREDUCE_UMIN) &&
13194 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMIN ||
13195 FalseVal->getOpcode() == ISD::VECREDUCE_SMIN) &&
13200 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMAX ||
13201 FalseVal->getOpcode() == ISD::VECREDUCE_UMAX) &&
13206 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMAX ||
13207 FalseVal->getOpcode() == ISD::VECREDUCE_SMAX) &&
13216 switch (TrueVal->getOpcode()) {
13217 case ISD::VECREDUCE_UMIN:
13218 case ISD::VECREDUCE_SMIN:
13219 case ISD::VECREDUCE_UMAX:
13220 case ISD::VECREDUCE_SMAX:
13235 if (TrueVal !=
LHS || FalseVal !=
RHS)
13238 EVT LeftType =
LHS->getValueType(0);
13239 EVT RightType =
RHS->getValueType(0);
13242 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13246 if (VectorScalarType != MVT::i32)
13254 if (VectorScalarType != MVT::i32)
13267 EVT VT =
N->getValueType(0);
13275 Shft =
N->getOperand(0);
13282 Cmp.getOperand(0) !=
N->getOperand(1) ||
13283 Cmp.getOperand(1) !=
N->getOperand(2))
13285 Shft =
N->getOperand(1);
13297 ScalarType = MVT::i8;
13300 case (1 << 15) - 1:
13301 ScalarType = MVT::i16;
13304 case (1ULL << 31) - 1:
13305 ScalarType = MVT::i32;
13336 unsigned LegalLanes = 128 / (ShftAmt + 1);
13360 for (
unsigned I = 0;
I < NumParts; ++
I) {
13377 if (!Subtarget->hasMVEIntegerOps())
13392 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13402 if (!Const || !Const->isOne())
13420 EVT VT =
N->getValueType(0);
13422 if (!Subtarget->hasMVEIntegerOps() ||
13451 Opc = Intrinsic::arm_mve_vctp64;
13454 Opc = Intrinsic::arm_mve_vctp32;
13457 Opc = Intrinsic::arm_mve_vctp16;
13460 Opc = Intrinsic::arm_mve_vctp8;
13514 EVT VT =
N->getValueType(0);
13520 switch (
Op.getOpcode()) {
13521 case ISD::VECREDUCE_ADD:
13545 unsigned N0RedOp = 0;
13552 unsigned N1RedOp = 0;
13566 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13568 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13575 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13599 if (!BaseLocDecomp0.getBase() ||
13600 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13601 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13603 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13605 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13615 if (IsBefore < 0) {
13618 }
else if (IsBefore > 0) {
13631 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13641 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13651 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13653 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13660 if (!Subtarget->hasMVEIntegerOps())
13666 EVT VT =
N->getValueType(0);
13671 if (VT != MVT::i64)
13682 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13702 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13751 "Expected shift op");
13753 SDValue ShiftLHS =
N->getOperand(0);
13767 if (Subtarget->isThumb1Only()) {
13778 if (Const->getAPIntValue().ult(256))
13781 Const->getAPIntValue().sgt(-256))
13797 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13798 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13799 "Expected XOR(SHIFT) pattern");
13804 if (XorC && ShiftC) {
13805 unsigned MaskIdx, MaskLen;
13806 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13807 unsigned ShiftAmt = ShiftC->getZExtValue();
13808 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13809 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13810 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13811 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13821 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13823 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13824 "Expected shift-shift mask");
13826 if (!Subtarget->isThumb1Only())
13836 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13838 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13843 if (!Subtarget->hasNEON()) {
13844 if (Subtarget->isThumb1Only())
13858 return Subtarget->hasVFP2Base();
13860 return Subtarget->hasVFP2Base();
13862 return Subtarget->hasFP64();
13865 return Subtarget->hasMVEFloatOps();
13894 if (ST->isThumb() && ST->isThumb1Only())
13898 for (
auto *U :
N->users()) {
13899 switch(U->getOpcode()) {
13917 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13918 U->getOperand(1).getOpcode() ==
ISD::SHL)
13928 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13935 if (!C1ShlC2 || !C2)
13938 APInt C2Int = C2->getAPIntValue();
13939 APInt C1Int = C1ShlC2->getAPIntValue();
13941 if (C2Int.
uge(C2Width))
13947 if ((C1Int & Mask) != C1Int)
13954 auto LargeImm = [](
const APInt &Imm) {
13955 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13956 return Imm.getBitWidth() - Zeros > 8;
13959 if (LargeImm(C1Int) || LargeImm(C2Int))
13971 SHL.dump();
N->dump());
14006 if (CSINC.getOpcode() !=
ARMISD::CSINC || !CSINC.hasOneUse())
14015 CSINC.getOperand(0)),
14016 CSINC.getOperand(1), CSINC.getOperand(2),
14017 CSINC.getOperand(3));
14074 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14116 if (!Subtarget->hasVMLxForwarding())
14135 EVT VT =
N->getValueType(0);
14146 EVT VT =
N->getValueType(0);
14147 if (VT != MVT::v2i64)
14158 return Op->getOperand(0);
14171 if (
And->getOpcode() == ISD::BITCAST)
14172 And =
And->getOperand(0);
14176 if (Mask->getOpcode() == ISD::BITCAST)
14177 Mask = Mask->getOperand(0);
14180 Mask.getValueType() != MVT::v4i32)
14186 return And->getOperand(0);
14191 if (
SDValue Op0 = IsSignExt(N0)) {
14192 if (
SDValue Op1 = IsSignExt(N1)) {
14198 if (
SDValue Op0 = IsZeroExt(N0)) {
14199 if (
SDValue Op1 = IsZeroExt(N1)) {
14214 EVT VT =
N->getValueType(0);
14215 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14226 if (VT != MVT::i32)
14233 int64_t MulAmt =
C->getSExtValue();
14236 ShiftAmt = ShiftAmt & (32 - 1);
14241 MulAmt >>= ShiftAmt;
14302 if (
N->getValueType(0) != MVT::i32)
14311 if (C1 == 255 || C1 == 65535)
14314 SDNode *N0 =
N->getOperand(0).getNode();
14328 if (!C2 || C2 >= 32)
14372 if (Trailing == C2 && C2 + C3 < 32) {
14385 if (Leading == C2 && C2 + C3 < 32) {
14413 EVT VT =
N->getValueType(0);
14417 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14420 APInt SplatBits, SplatUndef;
14421 unsigned SplatBitSize;
14423 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14424 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14425 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14426 SplatBitSize == 64) {
14460 if (!Subtarget->hasV6Ops() ||
14461 (Subtarget->isThumb() &&
14462 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14465 SDValue SRL = OR->getOperand(0);
14466 SDValue SHL = OR->getOperand(1);
14469 SRL = OR->getOperand(1);
14470 SHL = OR->getOperand(0);
14477 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14481 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14482 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14483 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14502 unsigned Opcode = 0;
14503 if (
isS16(OpS16, DAG))
14521 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14524 EVT VT =
N->getValueType(0);
14539 if (VT != MVT::i32)
14552 if (Mask == 0xffff)
14559 if ((Val & ~Mask) != Val)
14584 (Mask == ~Mask2)) {
14587 if (Subtarget->hasDSP() &&
14588 (Mask == 0xffff || Mask == 0xffff0000))
14601 (~Mask == Mask2)) {
14604 if (Subtarget->hasDSP() &&
14605 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14671 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14678 EVT VT =
N->getValueType(0);
14683 auto IsFreelyInvertable = [&](
SDValue V) {
14690 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14706 EVT VT =
N->getValueType(0);
14712 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14713 VT == MVT::v8i1 || VT == MVT::v16i1))
14716 APInt SplatBits, SplatUndef;
14717 unsigned SplatBitSize;
14719 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14720 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14721 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14722 SplatBitSize == 64) {
14758 unsigned SplatBitSize;
14761 APInt SplatBits0, SplatBits1;
14765 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14766 HasAnyUndefs) && !HasAnyUndefs) {
14767 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14768 HasAnyUndefs) && !HasAnyUndefs) {
14773 SplatBits0 == ~SplatBits1) {
14803 EVT VT =
N->getValueType(0);
14818 if (Subtarget->hasMVEIntegerOps()) {
14849 ToMask =
~N->getConstantOperandAPInt(2);
14869 unsigned LastActiveBitInA =
A.countr_zero();
14870 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14871 return LastActiveBitInA - 1 == FirstActiveBitInB;
14876 APInt ToMask, FromMask;
14884 APInt NewToMask, NewFromMask;
14886 if (NewFrom != From)
14890 if ((NewToMask & ToMask).getBoolValue())
14915 unsigned InvMask =
N->getConstantOperandVal(2);
14919 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14920 "undefined behavior");
14921 unsigned Mask = (1u << Width) - 1;
14923 if ((Mask & (~Mask2)) == 0)
14925 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14932 APInt ToMask1, FromMask1;
14935 APInt ToMask2, FromMask2;
14941 APInt NewFromMask = FromMask1 | FromMask2;
14942 APInt NewToMask = ToMask1 | ToMask2;
14944 EVT VT =
N->getValueType(0);
14947 if (NewFromMask[0] == 0)
14959 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14960 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14962 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14966 EVT VT =
N->getValueType(0);
14969 N->getOperand(1),
N->getOperand(2));
14983 SDValue CSInc = Cmp->getOperand(0);
15033 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15034 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15037 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15039 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15052 SDValue InDouble =
N->getOperand(0);
15067 SDValue BasePtr = LD->getBasePtr();
15069 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15070 LD->getAlign(), LD->getMemOperand()->getFlags());
15076 LD->getPointerInfo().getWithOffset(4),
15078 LD->getMemOperand()->getFlags());
15094 bool BVSwap = BV.
getOpcode() == ISD::BITCAST;
15099 BVSwap = BV.
getOpcode() == ISD::BITCAST;
15111 if (!Subtarget->
isLittle() && BVSwap)
15129 if (!Subtarget->
isLittle() && BVSwap)
15172 if (Op0->
getOpcode() == ISD::BITCAST) {
15174 if (Copy.getValueType() == MVT::f32 &&
15176 bool HasGlue = Copy->getNumOperands() == 3;
15177 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15178 HasGlue ? Copy->getOperand(2) :
SDValue()};
15179 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15198 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15199 LN0->getMemoryVT() == MVT::i16) {
15202 LN0->getBasePtr(), LN0->getMemOperand());
15220 EVT VT =
N->getValueType(0);
15254 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15255 for (
unsigned i = 0; i < NumElts; ++i) {
15256 SDNode *Elt =
N->getOperand(i).getNode();
15273 if (
N->getNumOperands() == 2)
15279 EVT VT =
N->getValueType(0);
15285 for (
unsigned i = 0; i < NumElts; ++i) {
15286 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(i));
15293 return DAG.
getNode(ISD::BITCAST, dl, VT, BV);
15311 EVT VT =
N->getValueType(0);
15319 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15323 if (
Use->getOpcode() != ISD::BITCAST ||
15324 Use->getValueType(0).isFloatingPoint())
15332 unsigned NumOfBitCastedElts = 0;
15334 unsigned NumOfRelevantElts = NumElts;
15335 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15337 if (Elt->
getOpcode() == ISD::BITCAST) {
15340 ++NumOfBitCastedElts;
15344 --NumOfRelevantElts;
15348 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15366 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15370 if (V.getOpcode() == ISD::BITCAST &&
15371 V->getOperand(0).getValueType() == MVT::i32)
15373 V = V.getOperand(0);
15382 Vec = DAG.
getNode(ISD::BITCAST, dl, VT, Vec);
15390 EVT VT =
N->getValueType(0);
15397 if (
Op->getOperand(0).getValueType() == VT)
15398 return Op->getOperand(0);
15413 if (
Op.getValueType() == MVT::i32) {
15424 EVT VT =
N->getValueType(0);
15429 if (ST->isLittle())
15430 return DAG.
getNode(ISD::BITCAST, dl, VT,
Op);
15433 if (
Op.getValueType() == VT)
15442 if (
Op->getOperand(0).getValueType() == VT)
15443 return Op->getOperand(0);
15452 if (!Subtarget->hasMVEIntegerOps())
15455 EVT VT =
N->getValueType(0);
15486 EVT VT =
N->getValueType(0);
15487 SDNode *Elt =
N->getOperand(1).getNode();
15496 SDValue Vec = DAG.
getNode(ISD::BITCAST, dl, FloatVT,
N->getOperand(0));
15497 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(1));
15502 Vec, V,
N->getOperand(2));
15503 return DAG.
getNode(ISD::BITCAST, dl, VT, InsElt);
15512 EVT VT =
N->getValueType(0);
15520 if (Ext.getOpcode() == ISD::BITCAST &&
15521 Ext.getOperand(0).getValueType() == MVT::f32)
15522 Ext = Ext.getOperand(0);
15525 Ext.getConstantOperandVal(1) % 2 != 0)
15527 if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() ==
ISD::SINT_TO_FP ||
15531 SDValue Op0 = Ext.getOperand(0);
15534 unsigned Lane = Ext.getConstantOperandVal(1);
15540 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15541 isa<ConstantSDNode>(V->getOperand(1)) &&
15542 V->getConstantOperandVal(1) == Lane + 1 &&
15543 V->getOperand(0).getResNo() == ResNo;
15545 if (OtherIt == Op0->
users().
end())
15550 SDValue OtherExt(*OtherIt, 0);
15563 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15575 EVT VT =
N->getValueType(0);
15581 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15583 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15585 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15588 while (
X.getValueType() != VT &&
X->getOpcode() == ISD::BITCAST)
15589 X =
X->getOperand(0);
15590 if (
X.getValueType() == VT)
15598 return Op0.
getOperand(
N->getConstantOperandVal(1));
15608 unsigned Offset =
N->getConstantOperandVal(1);
15620 unsigned Idx =
N->getConstantOperandVal(1);
15634 EVT VT =
N->getValueType(0);
15639 Op.getOperand(0).getValueType().getScalarType())
15649 SDValue SubVec =
N->getOperand(1);
15650 uint64_t IdxVal =
N->getConstantOperandVal(2);
15661 if (IdxVal == 0 && Vec.
isUndef())
15667 (IdxVal != 0 && IdxVal != NumSubElts))
15740 EVT VT =
N->getValueType(0);
15751 unsigned HalfElts = NumElts/2;
15753 for (
unsigned n = 0; n < NumElts; ++n) {
15756 if (MaskElt < (
int)HalfElts)
15758 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15759 NewElt = HalfElts + MaskElt - NumElts;
15802 bool SimpleConstIncOnly,
15810 bool isLoadOp =
true;
15811 bool isLaneOp =
false;
15814 bool hasAlignment =
true;
15815 unsigned NewOpc = 0;
15816 unsigned NumVecs = 0;
15817 if (
Target.isIntrinsic) {
15818 unsigned IntNo =
N->getConstantOperandVal(1);
15822 case Intrinsic::arm_neon_vld1:
15826 case Intrinsic::arm_neon_vld2:
15830 case Intrinsic::arm_neon_vld3:
15834 case Intrinsic::arm_neon_vld4:
15838 case Intrinsic::arm_neon_vld1x2:
15841 hasAlignment =
false;
15843 case Intrinsic::arm_neon_vld1x3:
15846 hasAlignment =
false;
15848 case Intrinsic::arm_neon_vld1x4:
15851 hasAlignment =
false;
15853 case Intrinsic::arm_neon_vld2dup:
15857 case Intrinsic::arm_neon_vld3dup:
15861 case Intrinsic::arm_neon_vld4dup:
15865 case Intrinsic::arm_neon_vld2lane:
15870 case Intrinsic::arm_neon_vld3lane:
15875 case Intrinsic::arm_neon_vld4lane:
15880 case Intrinsic::arm_neon_vst1:
15885 case Intrinsic::arm_neon_vst2:
15890 case Intrinsic::arm_neon_vst3:
15895 case Intrinsic::arm_neon_vst4:
15900 case Intrinsic::arm_neon_vst2lane:
15906 case Intrinsic::arm_neon_vst3lane:
15912 case Intrinsic::arm_neon_vst4lane:
15918 case Intrinsic::arm_neon_vst1x2:
15922 hasAlignment =
false;
15924 case Intrinsic::arm_neon_vst1x3:
15928 hasAlignment =
false;
15930 case Intrinsic::arm_neon_vst1x4:
15934 hasAlignment =
false;
15939 switch (
N->getOpcode()) {
15975 VecTy =
N->getValueType(0);
15976 }
else if (
Target.isIntrinsic) {
15977 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
15980 "Node has to be a load, a store, or an intrinsic!");
15981 VecTy =
N->getOperand(1).getValueType();
15989 if (isLaneOp || isVLDDUPOp)
15992 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
15998 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16007 EVT AlignedVecTy = VecTy;
16027 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16028 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16039 Alignment =
Align(1);
16045 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16047 for (n = 0; n < NumResultVecs; ++n)
16048 Tys[n] = AlignedVecTy;
16049 Tys[n++] = MVT::i32;
16050 Tys[n] = MVT::Other;
16055 Ops.push_back(
N->getOperand(0));
16056 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16061 Ops.push_back(StN->getValue());
16065 unsigned LastOperand =
16066 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16067 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16068 Ops.push_back(
N->getOperand(i));
16076 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::STORE) {
16078 StVal = DAG.
getNode(ISD::BITCAST, dl, AlignedVecTy, StVal);
16087 for (
unsigned i = 0; i < NumResultVecs; ++i)
16092 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::LOAD) {
16093 SDValue &LdVal = NewResults[0];
16094 LdVal = DAG.
getNode(ISD::BITCAST, dl, VecTy, LdVal);
16129 switch (
N->getOpcode()) {
16133 *
Ptr =
N->getOperand(0);
16134 *CInc =
N->getOperand(1);
16141 *
Ptr =
N->getOperand(1);
16142 *CInc =
N->getOperand(2);
16161 const bool isStore =
N->getOpcode() == ISD::STORE;
16169 SDValue Addr =
N->getOperand(AddrOpIdx);
16180 unsigned ConstInc =
16185 if (BaseUpdates.
size() >= MaxBaseUpdates)
16205 unsigned UserOffset =
16208 if (!UserOffset || UserOffset <=
Offset)
16211 unsigned NewConstInc = UserOffset -
Offset;
16214 if (BaseUpdates.
size() >= MaxBaseUpdates)
16221 unsigned NumValidUpd = BaseUpdates.
size();
16222 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16233 return LHS.ConstInc <
RHS.ConstInc;
16262 unsigned IntNo =
N->getConstantOperandVal(1);
16263 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16265 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16288 bool isLoadOp =
true;
16289 unsigned NewOpc = 0;
16290 unsigned NumVecs = 0;
16294 case Intrinsic::arm_mve_vld2q:
16298 case Intrinsic::arm_mve_vld4q:
16302 case Intrinsic::arm_mve_vst2q:
16307 case Intrinsic::arm_mve_vst4q:
16317 VecTy =
N->getValueType(0);
16319 VecTy =
N->getOperand(3).getValueType();
16333 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16335 for (n = 0; n < NumResultVecs; ++n)
16337 Tys[n++] = MVT::i32;
16338 Tys[n] = MVT::Other;
16343 Ops.push_back(
N->getOperand(0));
16344 Ops.push_back(
N->getOperand(2));
16345 Ops.push_back(Inc);
16347 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16348 Ops.push_back(
N->getOperand(i));
16355 for (
unsigned i = 0; i < NumResultVecs; ++i)
16374 EVT VT =
N->getValueType(0);
16380 SDNode *VLD =
N->getOperand(0).getNode();
16383 unsigned NumVecs = 0;
16384 unsigned NewOpc = 0;
16386 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16389 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16392 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16404 if (
Use.getResNo() == NumVecs)
16408 VLDLaneNo !=
User->getConstantOperandVal(1))
16415 for (n = 0; n < NumVecs; ++n)
16417 Tys[n] = MVT::Other;
16427 unsigned ResNo =
Use.getResNo();
16429 if (ResNo == NumVecs)
16436 std::vector<SDValue> VLDDupResults;
16437 for (
unsigned n = 0; n < NumVecs; ++n)
16451 EVT VT =
N->getValueType(0);
16454 if (Subtarget->hasMVEIntegerOps()) {
16458 ExtractVT = MVT::i32;
16460 N->getOperand(0),
N->getOperand(1));
16471 while (
Op.getOpcode() == ISD::BITCAST)
16472 Op =
Op.getOperand(0);
16477 unsigned EltSize =
Op.getScalarValueSizeInBits();
16479 unsigned Imm =
Op.getConstantOperandVal(0);
16495 if (Subtarget->hasMVEIntegerOps()) {
16498 if (
Op.getValueType() == MVT::f32)
16500 DAG.
getNode(ISD::BITCAST, dl, MVT::i32,
Op));
16501 else if (
Op.getValueType() == MVT::f16)
16506 if (!Subtarget->hasNEON())
16513 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16514 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16515 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16520 LD->getMemoryVT(), LD->getMemOperand());
16531 EVT VT =
N->getValueType(0);
16553 assert(StVT != VT &&
"Cannot truncate to the same type");
16563 if (0 != (NumElems * FromEltSz) % ToEltSz)
16566 unsigned SizeRatio = FromEltSz / ToEltSz;
16571 NumElems * SizeRatio);
16577 for (
unsigned i = 0; i < NumElems; ++i)
16591 MVT StoreType = MVT::i8;
16593 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16613 for (
unsigned I = 0;
I <
E;
I++) {
16644 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16647 unsigned NumElements = 4;
16664 unsigned Off0 = Rev ? NumElts : 0;
16665 unsigned Off1 = Rev ? 0 : NumElts;
16667 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16668 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16670 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16678 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16698 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16713 NewToVT, Alignment, MMOFlags, AAInfo);
16746 unsigned NewOffset =
16754 NewToVT, Alignment, MMOFlags, AAInfo);
16776 {Extract.getOperand(0), Extract.getOperand(1)});
16807 if (Subtarget->hasNEON())
16811 if (Subtarget->hasMVEFloatOps())
16815 if (Subtarget->hasMVEIntegerOps()) {
16890 if (!Subtarget->hasNEON())
16894 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16902 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16904 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16905 uint32_t IntBits = IntTy.getSizeInBits();
16906 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16907 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16918 if (
C == -1 ||
C == 0 ||
C > 32)
16923 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16924 Intrinsic::arm_neon_vcvtfp2fxu;
16927 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16930 if (IntBits < FloatBits)
16938 if (!Subtarget->hasMVEFloatOps())
16946 EVT VT =
N->getValueType(0);
16951 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16952 if (
Op.getOpcode() != ISD::BITCAST ||
16955 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16956 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16958 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16971 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
16982 EVT VT =
N->getValueType(0);
16985 if (!
N->getFlags().hasAllowReassociation())
16992 unsigned Opc =
A.getConstantOperandVal(0);
16993 if (
Opc != Intrinsic::arm_mve_vcmlaq)
16998 A.getOperand(3),
A.getOperand(4));
17030 if (!Subtarget->hasNEON())
17034 unsigned OpOpcode =
Op.getNode()->getOpcode();
17035 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17039 SDValue ConstVec =
N->getOperand(1);
17043 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17045 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17046 uint32_t IntBits = IntTy.getSizeInBits();
17047 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17048 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17068 int32_t
C = IntVal.exactLogBase2();
17069 if (
C == -1 ||
C == 0 ||
C > 32)
17075 if (IntBits < FloatBits)
17077 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17079 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17080 : Intrinsic::arm_neon_vcvtfxu2fp;
17088 if (!ST->hasMVEIntegerOps())
17091 assert(
N->getOpcode() == ISD::VECREDUCE_ADD);
17092 EVT ResVT =
N->getValueType(0);
17120 EVT AVT =
A.getValueType();
17126 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17127 EVT AVT =
A.getValueType();
17135 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17136 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17139 if (ExtTypeMatches(
A, ExtTypes))
17140 return ExtendIfNeeded(
A, ExtendCode);
17143 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17150 if (Ext->getOpcode() != ExtendCode)
17153 if (ExtTypeMatches(
A, ExtTypes))
17154 return ExtendIfNeeded(
A, ExtendCode);
17157 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17167 if (ResVT != RetTy)
17170 if (
Mul->getOpcode() == ExtendCode &&
17171 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17173 Mul =
Mul->getOperand(0);
17182 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17183 A = ExtendIfNeeded(
A, ExtendCode);
17184 B = ExtendIfNeeded(
B, ExtendCode);
17189 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17202 if (
Mul->getOpcode() == ExtendCode &&
17203 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17205 Mul =
Mul->getOperand(0);
17214 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17215 A = ExtendIfNeeded(
A, ExtendCode);
17216 B = ExtendIfNeeded(
B, ExtendCode);
17227 EVT VT =
Ops[0].getValueType();
17228 if (VT == MVT::v16i8) {
17230 "Unexpected illegal long reduction opcode");
17259 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17262 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17326 Op =
Op->getOperand(1);
17328 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17330 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17336 return DAG.
getNode(ISD::VECREDUCE_ADD, dl, ResVT, Ext);
17347 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17349 if (!Shuf || !Shuf->getOperand(1).isUndef())
17354 APInt SetElts(Mask.size(), 0);
17355 for (
int E : Mask) {
17363 if (
N->getNumOperands() != VecOp + 1) {
17365 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17371 if (
Op.getValueType().isVector())
17372 Ops.push_back(
Op.getOperand(0));
17383 unsigned IsTop =
N->getConstantOperandVal(2);
17390 if (Op0->
isUndef() && !IsTop)
17404 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17406 APInt Op0DemandedElts =
17407 IsTop ? Op1DemandedElts
17422 unsigned IsTop =
N->getConstantOperandVal(2);
17424 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17425 APInt Op0DemandedElts =
17437 EVT VT =
N->getValueType(0);
17444 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17445 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17449 LHS.getOperand(0),
RHS.getOperand(0));
17464 int ShiftAmt =
C->getSExtValue();
17465 if (ShiftAmt == 0) {
17471 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17472 unsigned NewOpcode =
17488 unsigned IntNo =
N->getConstantOperandVal(0);
17499 case Intrinsic::arm_neon_vshifts:
17500 case Intrinsic::arm_neon_vshiftu:
17501 case Intrinsic::arm_neon_vrshifts:
17502 case Intrinsic::arm_neon_vrshiftu:
17503 case Intrinsic::arm_neon_vrshiftn:
17504 case Intrinsic::arm_neon_vqshifts:
17505 case Intrinsic::arm_neon_vqshiftu:
17506 case Intrinsic::arm_neon_vqshiftsu:
17507 case Intrinsic::arm_neon_vqshiftns:
17508 case Intrinsic::arm_neon_vqshiftnu:
17509 case Intrinsic::arm_neon_vqshiftnsu:
17510 case Intrinsic::arm_neon_vqrshiftns:
17511 case Intrinsic::arm_neon_vqrshiftnu:
17512 case Intrinsic::arm_neon_vqrshiftnsu: {
17513 EVT VT =
N->getOperand(1).getValueType();
17515 unsigned VShiftOpc = 0;
17518 case Intrinsic::arm_neon_vshifts:
17519 case Intrinsic::arm_neon_vshiftu:
17524 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17531 case Intrinsic::arm_neon_vrshifts:
17532 case Intrinsic::arm_neon_vrshiftu:
17537 case Intrinsic::arm_neon_vqshifts:
17538 case Intrinsic::arm_neon_vqshiftu:
17543 case Intrinsic::arm_neon_vqshiftsu:
17548 case Intrinsic::arm_neon_vrshiftn:
17549 case Intrinsic::arm_neon_vqshiftns:
17550 case Intrinsic::arm_neon_vqshiftnu:
17551 case Intrinsic::arm_neon_vqshiftnsu:
17552 case Intrinsic::arm_neon_vqrshiftns:
17553 case Intrinsic::arm_neon_vqrshiftnu:
17554 case Intrinsic::arm_neon_vqrshiftnsu:
17566 case Intrinsic::arm_neon_vshifts:
17567 case Intrinsic::arm_neon_vshiftu:
17570 case Intrinsic::arm_neon_vrshifts:
17573 case Intrinsic::arm_neon_vrshiftu:
17576 case Intrinsic::arm_neon_vrshiftn:
17579 case Intrinsic::arm_neon_vqshifts:
17582 case Intrinsic::arm_neon_vqshiftu:
17585 case Intrinsic::arm_neon_vqshiftsu:
17588 case Intrinsic::arm_neon_vqshiftns:
17591 case Intrinsic::arm_neon_vqshiftnu:
17594 case Intrinsic::arm_neon_vqshiftnsu:
17597 case Intrinsic::arm_neon_vqrshiftns:
17600 case Intrinsic::arm_neon_vqrshiftnu:
17603 case Intrinsic::arm_neon_vqrshiftnsu:
17609 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17610 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17613 case Intrinsic::arm_neon_vshiftins: {
17614 EVT VT =
N->getOperand(1).getValueType();
17616 unsigned VShiftOpc = 0;
17620 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17627 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17628 N->getOperand(1),
N->getOperand(2),
17632 case Intrinsic::arm_neon_vqrshifts:
17633 case Intrinsic::arm_neon_vqrshiftu:
17637 case Intrinsic::arm_neon_vbsl: {
17640 N->getOperand(2),
N->getOperand(3));
17642 case Intrinsic::arm_mve_vqdmlah:
17643 case Intrinsic::arm_mve_vqdmlash:
17644 case Intrinsic::arm_mve_vqrdmlah:
17645 case Intrinsic::arm_mve_vqrdmlash:
17646 case Intrinsic::arm_mve_vmla_n_predicated:
17647 case Intrinsic::arm_mve_vmlas_n_predicated:
17648 case Intrinsic::arm_mve_vqdmlah_predicated:
17649 case Intrinsic::arm_mve_vqdmlash_predicated:
17650 case Intrinsic::arm_mve_vqrdmlah_predicated:
17651 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17656 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17663 case Intrinsic::arm_mve_minv:
17664 case Intrinsic::arm_mve_maxv:
17665 case Intrinsic::arm_mve_minav:
17666 case Intrinsic::arm_mve_maxav:
17667 case Intrinsic::arm_mve_minv_predicated:
17668 case Intrinsic::arm_mve_maxv_predicated:
17669 case Intrinsic::arm_mve_minav_predicated:
17670 case Intrinsic::arm_mve_maxav_predicated: {
17673 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17680 case Intrinsic::arm_mve_addv: {
17683 bool Unsigned =
N->getConstantOperandVal(2);
17688 case Intrinsic::arm_mve_addlv:
17689 case Intrinsic::arm_mve_addlv_predicated: {
17692 bool Unsigned =
N->getConstantOperandVal(2);
17693 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17698 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17700 Ops.push_back(
N->getOperand(i));
17721 EVT VT =
N->getValueType(0);
17723 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17724 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17725 N->getOperand(0)->hasOneUse()) {
17742 if (AndMask == 255 || AndMask == 65535)
17746 if (MaskedBits > ShiftAmt) {
17761 if (ST->hasMVEIntegerOps())
17766 switch (
N->getOpcode()) {
17779 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17780 unsigned VShiftOpc =
17783 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17799 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17802 EVT FromVT = LD->getValueType(0);
17803 EVT ToVT =
N->getValueType(0);
17810 unsigned NumElements = 0;
17811 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17813 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17815 if (NumElements == 0 ||
17825 SDValue BasePtr = LD->getBasePtr();
17826 Align Alignment = LD->getBaseAlign();
17847 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17848 Alignment, MMOFlags, AAInfo);
17854 if (FromEltVT == MVT::f16) {
17857 for (
unsigned i = 0; i < Loads.
size(); i++) {
17883 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17887 EVT VT =
N->getValueType(0);
17891 if (VT == MVT::i32 &&
17892 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17897 switch (
N->getOpcode()) {
17911 if (ST->hasMVEIntegerOps())
17920 if (ST->hasMVEFloatOps())
17931 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17935 EVT VT =
Op.getValueType();
17938 if (VT != MVT::i32 ||
17951 APInt MaxC = Max.getConstantOperandAPInt(1);
17954 !(MinC + 1).isPowerOf2())
17972 EVT VT =
N->getValueType(0);
17975 if (VT == MVT::i32)
17978 if (!ST->hasMVEIntegerOps())
17984 if (VT != MVT::v4i32 && VT != MVT::v8i16)
17987 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
17995 if (VT == MVT::v4i32)
17996 SaturateC =
APInt(32, (1 << 15) - 1,
true);
17998 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18005 MaxC != ~SaturateC)
18010 if (IsSignedSaturate(
N, N0.
getNode())) {
18013 if (VT == MVT::v4i32) {
18014 HalfVT = MVT::v8i16;
18015 ExtVT = MVT::v4i16;
18017 HalfVT = MVT::v16i8;
18032 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18038 if (VT == MVT::v4i32)
18039 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18041 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18050 if (IsUnsignedSaturate(
N)) {
18054 if (VT == MVT::v4i32) {
18055 HalfVT = MVT::v8i16;
18056 ExtConst = 0x0000FFFF;
18058 HalfVT = MVT::v16i8;
18080 const APInt *CV = &
C->getAPIntValue();
18098 SDValue Op0 = CMOV->getOperand(0);
18099 SDValue Op1 = CMOV->getOperand(1);
18100 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
18101 SDValue CmpZ = CMOV->getOperand(3);
18137 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18144 if ((OrCI & Known.
Zero) != OrCI)
18150 EVT VT =
X.getValueType();
18151 unsigned BitInX = AndC->
logBase2();
18159 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18160 BitInY < NumActiveBits; ++BitInY) {
18161 if (OrCI[BitInY] == 0)
18164 Mask.setBit(BitInY);
18181 switch (
N->getOpcode()) {
18196 if (Const->isZero())
18198 else if (Const->isOne())
18206 unsigned IntOp =
N.getConstantOperandVal(1);
18207 if (IntOp != Intrinsic::test_start_loop_iterations &&
18208 IntOp != Intrinsic::loop_decrement_reg)
18234 bool Negate =
false;
18238 if (
N->getOpcode() == ISD::BRCOND) {
18240 Cond =
N->getOperand(1);
18241 Dest =
N->getOperand(2);
18243 assert(
N->getOpcode() == ISD::BR_CC &&
"Expected BRCOND or BR_CC!");
18245 Cond =
N->getOperand(2);
18246 Dest =
N->getOperand(4);
18248 if (!Const->isOne() && !Const->isZero())
18250 Imm = Const->getZExtValue();
18278 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18279 "unsupported condition");
18284 unsigned IntOp =
Int->getConstantOperandVal(1);
18285 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() == ISD::BR) &&
18286 "expected single br user");
18287 SDNode *Br = *
N->user_begin();
18297 if (IntOp == Intrinsic::test_start_loop_iterations) {
18301 if (IsTrueIfZero(CC, Imm)) {
18307 UpdateUncondBr(Br, Dest, DAG);
18309 SDValue Ops[] = {Chain, Setup, OtherTarget};
18322 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18326 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18330 if (
Target == OtherTarget)
18331 UpdateUncondBr(Br, Dest, DAG);
18351 SDValue LHS = Cmp.getOperand(0);
18352 SDValue RHS = Cmp.getOperand(1);
18362 LHS->getOperand(0)->hasOneUse() &&
18382 EVT VT =
N->getValueType(0);
18384 SDValue LHS = Cmp.getOperand(0);
18385 SDValue RHS = Cmp.getOperand(1);
18386 SDValue FalseVal =
N->getOperand(0);
18387 SDValue TrueVal =
N->getOperand(1);
18392 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18416 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18418 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18430 LHS->getOperand(2), LHS->getOperand(3));
18440 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18444 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18446 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18455 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18520 const APInt *TrueConst;
18521 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18522 ((FalseVal.getOpcode() ==
ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18523 FalseVal.getOperand(1) == RHS) ||
18527 unsigned ShiftAmount = TrueConst->
logBase2();
18542 if (Known.
Zero == 0xfffffffe)
18545 else if (Known.
Zero == 0xffffff00)
18548 else if (Known.
Zero == 0xffff0000)
18561 EVT DstVT =
N->getValueType(0);
18564 if (ST->hasMVEIntegerOps() && Src.getOpcode() ==
ARMISD::VDUP) {
18565 EVT SrcVT = Src.getValueType();
18573 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18574 Src.getValueType().getScalarSizeInBits())
18575 Src = Src.getOperand(0);
18579 EVT SrcVT = Src.getValueType();
18599 EVT VT =
N->getValueType(0);
18607 if (
N->getNumOperands() == 2 &&
18611 N->getOperand(0).getOperand(1),
18612 N->getOperand(1).getOperand(0),
18613 N->getOperand(1).getOperand(1));
18616 if (
N->getNumOperands() == 2 &&
18622 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18623 S0->getOperand(1) ==
S1->getOperand(1)) {
18626 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18646 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18647 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18648 (Op.getOpcode() == ISD::BITCAST &&
18649 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18652 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18654 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18672 int NumIns =
N->getNumOperands();
18673 assert((NumIns == 2 || NumIns == 4) &&
18674 "Expected 2 or 4 inputs to an MVETrunc");
18676 if (
N->getNumOperands() == 4)
18680 for (
int I = 0;
I < NumIns;
I++) {
18682 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18702 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18705 EVT FromVT = LD->getMemoryVT();
18706 EVT ToVT =
N->getValueType(0);
18713 unsigned NumElements = 0;
18714 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18716 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18718 assert(NumElements != 0);
18724 LD->getExtensionType() != NewExtType)
18731 SDValue BasePtr = LD->getBasePtr();
18732 Align Alignment = LD->getBaseAlign();
18751 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18752 Alignment, MMOFlags, AAInfo);
18768 EVT VT =
N->getValueType(0);
18770 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18771 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18773 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18775 auto Extend = [&](
SDValue V) {
18785 SDValue Ext = Extend(
N->getOperand(0));
18793 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18798 auto CheckInregMask = [&](
int Start,
int Offset) {
18800 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18806 if (CheckInregMask(0, 0))
18808 else if (CheckInregMask(0, 1))
18809 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18810 else if (CheckInregMask(0, Mask.size()))
18812 else if (CheckInregMask(0, Mask.size() + 1))
18813 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18818 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18822 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18829 if (
N->getOperand(0)->getOpcode() == ISD::LOAD)
18840 int NumOuts =
N->getNumValues();
18841 assert((NumOuts == 2 || NumOuts == 4) &&
18842 "Expected 2 or 4 outputs to an MVEEXT");
18843 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18845 if (
N->getNumOperands() == 4)
18851 StackPtr, MPI,
Align(4));
18854 for (
int I = 0;
I < NumOuts;
I++) {
18856 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18857 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18862 VT, Chain,
Ptr, MPI, LoadVT,
Align(4));
18871 switch (
N->getOpcode()) {
18922 case ISD::FP_EXTEND:
18961 case ISD::VECREDUCE_ADD:
18988 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18995 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19006 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19014 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19016 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19024 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19026 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19034 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19045 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19053 if (
N->getOperand(1) ==
N->getOperand(2))
19054 return N->getOperand(1);
19058 switch (
N->getConstantOperandVal(1)) {
19059 case Intrinsic::arm_neon_vld1:
19060 case Intrinsic::arm_neon_vld1x2:
19061 case Intrinsic::arm_neon_vld1x3:
19062 case Intrinsic::arm_neon_vld1x4:
19063 case Intrinsic::arm_neon_vld2:
19064 case Intrinsic::arm_neon_vld3:
19065 case Intrinsic::arm_neon_vld4:
19066 case Intrinsic::arm_neon_vld2lane:
19067 case Intrinsic::arm_neon_vld3lane:
19068 case Intrinsic::arm_neon_vld4lane:
19069 case Intrinsic::arm_neon_vld2dup:
19070 case Intrinsic::arm_neon_vld3dup:
19071 case Intrinsic::arm_neon_vld4dup:
19072 case Intrinsic::arm_neon_vst1:
19073 case Intrinsic::arm_neon_vst1x2:
19074 case Intrinsic::arm_neon_vst1x3:
19075 case Intrinsic::arm_neon_vst1x4:
19076 case Intrinsic::arm_neon_vst2:
19077 case Intrinsic::arm_neon_vst3:
19078 case Intrinsic::arm_neon_vst4:
19079 case Intrinsic::arm_neon_vst2lane:
19080 case Intrinsic::arm_neon_vst3lane:
19081 case Intrinsic::arm_neon_vst4lane:
19083 case Intrinsic::arm_mve_vld2q:
19084 case Intrinsic::arm_mve_vld4q:
19085 case Intrinsic::arm_mve_vst2q:
19086 case Intrinsic::arm_mve_vst4q:
19097 return (VT == MVT::f32) && (
Opc == ISD::LOAD ||
Opc == ISD::STORE);
19103 unsigned *
Fast)
const {
19109 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19112 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19114 if (AllowsUnaligned) {
19116 *
Fast = Subtarget->hasV7Ops();
19121 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19125 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19132 if (!Subtarget->hasMVEIntegerOps())
19136 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19137 Ty == MVT::v2i1)) {
19145 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19161 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19162 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19163 Ty == MVT::v2f64) {
19174 const AttributeList &FuncAttributes)
const {
19176 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19177 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19179 if (
Op.size() >= 16 &&
19185 }
else if (
Op.size() >= 8 &&
19202 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19204 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19206 return (SrcBits == 64 && DestBits == 32);
19215 return (SrcBits == 64 && DestBits == 32);
19251 return Subtarget->hasFullFP16();
19258 if (!Subtarget->hasMVEIntegerOps())
19277 if (Ld->isExpandingLoad())
19281 if (Subtarget->hasMVEIntegerOps())
19326bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19328 if (Subtarget->useSoftFloat())
19337 return Subtarget->hasMVEFloatOps();
19355 unsigned Scale = 1;
19372 if ((V & (Scale - 1)) != 0)
19381 if (VT.
isVector() && Subtarget->hasNEON())
19384 !Subtarget->hasMVEFloatOps())
19387 bool IsNeg =
false;
19393 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19396 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19412 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19418 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19448 default:
return false;
19467 int Scale = AM.
Scale;
19472 default:
return false;
19480 Scale = Scale & ~1;
19481 return Scale == 2 || Scale == 4 || Scale == 8;
19498 if (Scale & 1)
return false;
19505 const int Scale = AM.
Scale;
19515 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19531 switch (AM.
Scale) {
19542 if (Subtarget->isThumb1Only())
19545 if (Subtarget->isThumb2())
19548 int Scale = AM.
Scale;
19550 default:
return false;
19554 if (Scale < 0) Scale = -Scale;
19562 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19575 if (Scale & 1)
return false;
19588 if (!Subtarget->isThumb())
19591 if (Subtarget->isThumb2())
19595 return Imm >= 0 && Imm <= 255;
19605 if (!Subtarget->isThumb())
19607 if (Subtarget->isThumb2())
19610 return AbsImm <= 255;
19645 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19649 int RHSC = (int)
RHS->getZExtValue();
19650 if (RHSC < 0 && RHSC > -256) {
19660 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19663 int RHSC = (int)
RHS->getZExtValue();
19664 if (RHSC < 0 && RHSC > -0x1000) {
19706 int RHSC = (int)
RHS->getZExtValue();
19707 if (RHSC < 0 && RHSC > -0x100) {
19712 }
else if (RHSC > 0 && RHSC < 0x100) {
19723 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19734 bool CanChangeType = isLE && !IsMasked;
19737 int RHSC = (int)
RHS->getZExtValue();
19739 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19740 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19745 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19756 if (VT == MVT::v4i16) {
19757 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19759 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19760 if (IsInRange(RHSC, 0x80, 1))
19762 }
else if (Alignment >= 4 &&
19763 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19764 IsInRange(RHSC, 0x80, 4))
19766 else if (Alignment >= 2 &&
19767 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19768 IsInRange(RHSC, 0x80, 2))
19770 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19783 if (Subtarget->isThumb1Only())
19789 bool isSEXTLoad =
false;
19790 bool IsMasked =
false;
19792 Ptr = LD->getBasePtr();
19793 VT = LD->getMemoryVT();
19794 Alignment = LD->getAlign();
19797 Ptr = ST->getBasePtr();
19798 VT = ST->getMemoryVT();
19799 Alignment = ST->getAlign();
19801 Ptr = LD->getBasePtr();
19802 VT = LD->getMemoryVT();
19803 Alignment = LD->getAlign();
19807 Ptr = ST->getBasePtr();
19808 VT = ST->getMemoryVT();
19809 Alignment = ST->getAlign();
19815 bool isLegal =
false;
19817 isLegal = Subtarget->hasMVEIntegerOps() &&
19819 Ptr.getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19820 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19822 if (Subtarget->isThumb2())
19847 bool isSEXTLoad =
false, isNonExt;
19848 bool IsMasked =
false;
19850 VT = LD->getMemoryVT();
19851 Ptr = LD->getBasePtr();
19852 Alignment = LD->getAlign();
19856 VT = ST->getMemoryVT();
19857 Ptr = ST->getBasePtr();
19858 Alignment = ST->getAlign();
19859 isNonExt = !ST->isTruncatingStore();
19861 VT = LD->getMemoryVT();
19862 Ptr = LD->getBasePtr();
19863 Alignment = LD->getAlign();
19868 VT = ST->getMemoryVT();
19869 Ptr = ST->getBasePtr();
19870 Alignment = ST->getAlign();
19871 isNonExt = !ST->isTruncatingStore();
19876 if (Subtarget->isThumb1Only()) {
19879 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19880 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19883 if (!RHS || RHS->getZExtValue() != 4)
19885 if (Alignment <
Align(4))
19889 Base =
Op->getOperand(0);
19895 bool isLegal =
false;
19897 isLegal = Subtarget->hasMVEIntegerOps() &&
19902 if (Subtarget->isThumb2())
19916 !Subtarget->isThumb2())
19930 const APInt &DemandedElts,
19932 unsigned Depth)
const {
19935 switch (
Op.getOpcode()) {
19942 if (
Op.getResNo() == 0) {
19968 case Intrinsic::arm_ldaex:
19969 case Intrinsic::arm_ldrex: {
19984 const APInt &Mask =
Op.getConstantOperandAPInt(2);
19985 Known.
Zero &= Mask;
19991 const SDValue &SrcSV =
Op.getOperand(0);
19997 "VGETLANE index out of bounds");
20002 EVT VT =
Op.getValueType();
20009 Known = Known.
sext(DstSz);
20011 Known = Known.
zext(DstSz);
20019 Known = KnownOp.
zext(32);
20046 unsigned Encoded =
Op.getConstantOperandVal(1);
20047 unsigned DecEltBits = 0;
20050 unsigned EltBits =
Op.getScalarValueSizeInBits();
20051 if (EltBits != DecEltBits) {
20061 APInt Imm(DecEltBits, DecodedVal);
20063 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20064 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20082 EVT VT =
Op.getValueType();
20088 assert(VT == MVT::i32 &&
"Unexpected integer type");
20095 unsigned Mask =
C->getZExtValue();
20098 unsigned ShrunkMask = Mask & Demanded;
20099 unsigned ExpandedMask = Mask | ~Demanded;
20103 if (ShrunkMask == 0)
20109 if (ExpandedMask == ~0U)
20112 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20113 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20115 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20116 if (NewMask == Mask)
20125 if (IsLegalMask(0xFF))
20126 return UseMask(0xFF);
20129 if (IsLegalMask(0xFFFF))
20130 return UseMask(0xFFFF);
20134 if (ShrunkMask < 256)
20135 return UseMask(ShrunkMask);
20139 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20140 return UseMask(ExpandedMask);
20155 unsigned Depth)
const {
20156 unsigned Opc =
Op.getOpcode();
20164 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20166 unsigned ShAmt =
Op->getConstantOperandVal(2);
20178 unsigned ModImm =
Op.getConstantOperandVal(1);
20179 unsigned EltBits = 0;
20181 if ((OriginalDemandedBits & Mask) == 0)
20187 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20202 if (!Subtarget->hasVFP2Base())
20206 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20218 unsigned S = Constraint.
size();
20220 switch (Constraint[0]) {
20232 }
else if (S == 2) {
20233 switch (Constraint[0]) {
20250 Value *CallOperandVal =
info.CallOperandVal;
20253 if (!CallOperandVal)
20257 switch (*constraint) {
20263 if (Subtarget->isThumb())
20278 if (PR == 0 || VT == MVT::Other)
20280 if (ARM::SPRRegClass.
contains(PR))
20281 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20282 if (ARM::DPRRegClass.
contains(PR))
20287using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20291 switch (Constraint.
size()) {
20294 switch (Constraint[0]) {
20296 if (Subtarget->isThumb())
20297 return RCPair(0U, &ARM::tGPRRegClass);
20298 return RCPair(0U, &ARM::GPRRegClass);
20300 if (Subtarget->isThumb())
20301 return RCPair(0U, &ARM::hGPRRegClass);
20304 if (Subtarget->isThumb1Only())
20305 return RCPair(0U, &ARM::tGPRRegClass);
20306 return RCPair(0U, &ARM::GPRRegClass);
20308 if (VT == MVT::Other)
20310 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20311 return RCPair(0U, &ARM::SPRRegClass);
20313 return RCPair(0U, &ARM::DPRRegClass);
20315 return RCPair(0U, &ARM::QPRRegClass);
20318 if (VT == MVT::Other)
20320 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20321 return RCPair(0U, &ARM::SPR_8RegClass);
20323 return RCPair(0U, &ARM::DPR_8RegClass);
20325 return RCPair(0U, &ARM::QPR_8RegClass);
20328 if (VT == MVT::Other)
20330 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20331 return RCPair(0U, &ARM::SPRRegClass);
20333 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20335 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20341 if (Constraint[0] ==
'T') {
20342 switch (Constraint[1]) {
20346 return RCPair(0U, &ARM::tGPREvenRegClass);
20348 return RCPair(0U, &ARM::tGPROddRegClass);
20357 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20358 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20362 return {0,
nullptr};
20370 std::vector<SDValue> &
Ops,
20375 if (Constraint.
size() != 1)
20378 char ConstraintLetter = Constraint[0];
20379 switch (ConstraintLetter) {
20382 case 'I':
case 'J':
case 'K':
case 'L':
20383 case 'M':
case 'N':
case 'O':
20388 int64_t CVal64 =
C->getSExtValue();
20389 int CVal = (int) CVal64;
20392 if (CVal != CVal64)
20395 switch (ConstraintLetter) {
20399 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20400 if (CVal >= 0 && CVal <= 65535)
20404 if (Subtarget->isThumb1Only()) {
20407 if (CVal >= 0 && CVal <= 255)
20409 }
else if (Subtarget->isThumb2()) {
20423 if (Subtarget->isThumb1Only()) {
20428 if (CVal >= -255 && CVal <= -1)
20434 if (CVal >= -4095 && CVal <= 4095)
20440 if (Subtarget->isThumb1Only()) {
20447 }
else if (Subtarget->isThumb2()) {
20467 if (Subtarget->isThumb1Only()) {
20470 if (CVal >= -7 && CVal < 7)
20472 }
else if (Subtarget->isThumb2()) {
20492 if (Subtarget->isThumb1Only()) {
20495 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20501 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20507 if (Subtarget->isThumb1Only()) {
20509 if (CVal >= 0 && CVal <= 31)
20515 if (Subtarget->isThumb1Only()) {
20518 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20527 if (Result.getNode()) {
20528 Ops.push_back(Result);
20538 "Unhandled Opcode in getDivRemLibcall");
20544 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20545 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20546 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20547 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20556 "Unhandled Opcode in getDivRemArgList");
20560 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20561 EVT ArgVT =
N->getOperand(i).getValueType();
20566 Args.push_back(Entry);
20574 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20575 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20576 Subtarget->isTargetWindows()) &&
20577 "Register-based DivRem lowering only");
20578 unsigned Opcode =
Op->getOpcode();
20580 "Invalid opcode for Div/Rem lowering");
20582 EVT VT =
Op->getValueType(0);
20604 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20605 : Subtarget->hasDivideInARMMode();
20606 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20607 Op->getSimpleValueType(0) == MVT::i32) {
20609 const SDValue Dividend =
Op->getOperand(0);
20610 const SDValue Divisor =
Op->getOperand(1);
20611 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20615 SDValue Values[2] = {Div, Rem};
20632 if (Subtarget->isTargetWindows())
20635 TargetLowering::CallLoweringInfo CLI(DAG);
20640 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20641 return CallInfo.first;
20647 EVT VT =
N->getValueType(0);
20653 Result[0], Result[1]);
20657 std::vector<Type*> RetTyParams;
20658 Type *RetTyElement;
20668 RetTyParams.push_back(RetTyElement);
20669 RetTyParams.push_back(RetTyElement);
20682 if (Subtarget->isTargetWindows())
20690 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20693 SDNode *ResNode = CallResult.first.getNode();
20700 assert(Subtarget->isTargetWindows() &&
"unsupported target platform");
20708 "no-stack-arg-probe")) {
20712 Chain =
SP.getValue(1);
20729 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20740 bool IsStrict =
Op->isStrictFPOpcode();
20741 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20742 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20744 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20745 "Unexpected type for custom-lowering FP_EXTEND");
20747 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20748 "With both FP DP and 16, any FP conversion is legal!");
20750 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20751 "With FP16, 16 to 32 conversion is legal!");
20754 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20759 Loc,
Op.getValueType(), SrcVal);
20774 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20775 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20776 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20777 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20781 {DstVT, MVT::Other}, {Chain, SrcVal});
20784 SrcVal = DAG.
getNode(ISD::FP_EXTEND, Loc, DstVT, SrcVal);
20788 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20789 "Unexpected type for custom-lowering FP_EXTEND");
20790 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20795 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20799 bool IsStrict =
Op->isStrictFPOpcode();
20801 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20803 EVT DstVT =
Op.getValueType();
20804 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20807 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20808 "Unexpected type for custom-lowering FP_ROUND");
20810 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20811 "With both FP DP and 16, any FP conversion is legal!");
20816 if (SrcSz == 32 && Subtarget->hasFP16())
20821 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20822 "Unexpected type for custom-lowering FP_ROUND");
20826 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20838 if (v == 0xffffffff)
20850 bool ForCodeSize)
const {
20851 if (!Subtarget->hasVFP3Base())
20853 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20855 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20858 if (VT == MVT::f32)
20860 if (VT == MVT::f64 && Subtarget->hasFP64())
20873 case Intrinsic::arm_neon_vld1:
20874 case Intrinsic::arm_neon_vld2:
20875 case Intrinsic::arm_neon_vld3:
20876 case Intrinsic::arm_neon_vld4:
20877 case Intrinsic::arm_neon_vld2lane:
20878 case Intrinsic::arm_neon_vld3lane:
20879 case Intrinsic::arm_neon_vld4lane:
20880 case Intrinsic::arm_neon_vld2dup:
20881 case Intrinsic::arm_neon_vld3dup:
20882 case Intrinsic::arm_neon_vld4dup: {
20885 auto &
DL =
I.getDataLayout();
20886 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20888 Info.ptrVal =
I.getArgOperand(0);
20890 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20896 case Intrinsic::arm_neon_vld1x2:
20897 case Intrinsic::arm_neon_vld1x3:
20898 case Intrinsic::arm_neon_vld1x4: {
20901 auto &
DL =
I.getDataLayout();
20902 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20904 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20906 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20911 case Intrinsic::arm_neon_vst1:
20912 case Intrinsic::arm_neon_vst2:
20913 case Intrinsic::arm_neon_vst3:
20914 case Intrinsic::arm_neon_vst4:
20915 case Intrinsic::arm_neon_vst2lane:
20916 case Intrinsic::arm_neon_vst3lane:
20917 case Intrinsic::arm_neon_vst4lane: {
20920 auto &
DL =
I.getDataLayout();
20921 unsigned NumElts = 0;
20922 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20923 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20926 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20929 Info.ptrVal =
I.getArgOperand(0);
20931 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20937 case Intrinsic::arm_neon_vst1x2:
20938 case Intrinsic::arm_neon_vst1x3:
20939 case Intrinsic::arm_neon_vst1x4: {
20942 auto &
DL =
I.getDataLayout();
20943 unsigned NumElts = 0;
20944 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20945 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20948 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20951 Info.ptrVal =
I.getArgOperand(0);
20953 Info.align =
I.getParamAlign(0).valueOrOne();
20958 case Intrinsic::arm_mve_vld2q:
20959 case Intrinsic::arm_mve_vld4q: {
20963 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
20965 Info.ptrVal =
I.getArgOperand(0);
20972 case Intrinsic::arm_mve_vst2q:
20973 case Intrinsic::arm_mve_vst4q: {
20976 Type *VecTy =
I.getArgOperand(1)->getType();
20977 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
20979 Info.ptrVal =
I.getArgOperand(0);
20986 case Intrinsic::arm_mve_vldr_gather_base:
20987 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
20989 Info.ptrVal =
nullptr;
20991 Info.align =
Align(1);
20995 case Intrinsic::arm_mve_vldr_gather_base_wb:
20996 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
20998 Info.ptrVal =
nullptr;
20999 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21000 Info.align =
Align(1);
21004 case Intrinsic::arm_mve_vldr_gather_offset:
21005 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21007 Info.ptrVal =
nullptr;
21012 Info.align =
Align(1);
21016 case Intrinsic::arm_mve_vstr_scatter_base:
21017 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21019 Info.ptrVal =
nullptr;
21020 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21021 Info.align =
Align(1);
21025 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21026 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21028 Info.ptrVal =
nullptr;
21029 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21030 Info.align =
Align(1);
21034 case Intrinsic::arm_mve_vstr_scatter_offset:
21035 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21037 Info.ptrVal =
nullptr;
21042 Info.align =
Align(1);
21046 case Intrinsic::arm_ldaex:
21047 case Intrinsic::arm_ldrex: {
21048 auto &
DL =
I.getDataLayout();
21049 Type *ValTy =
I.getParamElementType(0);
21052 Info.ptrVal =
I.getArgOperand(0);
21054 Info.align =
DL.getABITypeAlign(ValTy);
21058 case Intrinsic::arm_stlex:
21059 case Intrinsic::arm_strex: {
21060 auto &
DL =
I.getDataLayout();
21061 Type *ValTy =
I.getParamElementType(1);
21064 Info.ptrVal =
I.getArgOperand(1);
21066 Info.align =
DL.getABITypeAlign(ValTy);
21070 case Intrinsic::arm_stlexd:
21071 case Intrinsic::arm_strexd:
21073 Info.memVT = MVT::i64;
21074 Info.ptrVal =
I.getArgOperand(2);
21076 Info.align =
Align(8);
21080 case Intrinsic::arm_ldaexd:
21081 case Intrinsic::arm_ldrexd:
21083 Info.memVT = MVT::i64;
21084 Info.ptrVal =
I.getArgOperand(0);
21086 Info.align =
Align(8);
21101 assert(Ty->isIntegerTy());
21103 unsigned Bits = Ty->getPrimitiveSizeInBits();
21104 if (Bits == 0 || Bits > 32)
21110 unsigned Index)
const {
21120 if (!Subtarget->hasDataBarrier()) {
21124 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21125 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21126 Builder.getInt32(0), Builder.getInt32(7),
21127 Builder.getInt32(10), Builder.getInt32(5)};
21128 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
21138 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
21159 if (Subtarget->preferISHSTBarriers())
21192 bool has64BitAtomicStore;
21193 if (Subtarget->isMClass())
21194 has64BitAtomicStore =
false;
21195 else if (Subtarget->isThumb())
21196 has64BitAtomicStore = Subtarget->hasV7Ops();
21198 has64BitAtomicStore = Subtarget->hasV6Ops();
21200 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21214 bool has64BitAtomicLoad;
21215 if (Subtarget->isMClass())
21216 has64BitAtomicLoad =
false;
21217 else if (Subtarget->isThumb())
21218 has64BitAtomicLoad = Subtarget->hasV7Ops();
21220 has64BitAtomicLoad = Subtarget->hasV6Ops();
21236 if (Subtarget->isMClass())
21237 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21238 else if (Subtarget->isThumb())
21239 hasAtomicRMW = Subtarget->hasV7Ops();
21241 hasAtomicRMW = Subtarget->hasV6Ops();
21242 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21265 bool HasAtomicCmpXchg;
21266 if (Subtarget->isMClass())
21267 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21268 else if (Subtarget->isThumb())
21269 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21271 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21273 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21280 return InsertFencesForAtomic;
21285 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21289 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21291 if (SecurityCheckCookieLibcall == RTLIB::Unsupported)
21295 M.getOrInsertGlobal(
"__security_cookie",
21303 F->addParamAttr(0, Attribute::AttrKind::InReg);
21308 RTLIB::LibcallImpl SecurityCheckCookie =
21310 if (SecurityCheckCookie != RTLIB::Unsupported)
21316 unsigned &
Cost)
const {
21318 if (!Subtarget->hasNEON())
21347 unsigned Opcode =
Op.getOpcode();
21358 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21362 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21367 if (!Subtarget->hasV7Ops())
21373 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21375 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21383 if (Subtarget->hasMinSize() && !Subtarget->isTargetWindows())
21392 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21398 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21400 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21403 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21405 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21406 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21407 if (!Subtarget->isLittle())
21409 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21410 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21411 return Builder.CreateOr(
21412 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21416 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21417 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21420 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21421 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21426 if (!Subtarget->hasV7Ops())
21428 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21434 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21442 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21446 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21447 if (!Subtarget->isLittle())
21449 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21452 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21456 CallInst *CI = Builder.CreateCall(
21457 Strex, {Builder.CreateZExtOrBitCast(
21467 return Subtarget->isMClass();
21475 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21482 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21485 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21493 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21501 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21504 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21509 if (Subtarget->hasNEON() && VecSize == 64)
21511 return VecSize % 128 == 0;
21515 if (Subtarget->hasNEON())
21517 if (Subtarget->hasMVEIntegerOps())
21537 "Invalid interleave factor");
21538 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21540 "Unmatched number of shufflevectors and indices");
21545 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21548 Type *EltTy = VecTy->getElementType();
21551 Align Alignment = LI->getAlign();
21569 Value *BaseAddr = LI->getPointerOperand();
21571 if (NumLoads > 1) {
21575 VecTy->getNumElements() / NumLoads);
21581 if (Subtarget->hasNEON()) {
21582 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21583 Type *Tys[] = {VecTy, PtrTy};
21584 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21585 Intrinsic::arm_neon_vld3,
21586 Intrinsic::arm_neon_vld4};
21589 Ops.push_back(BaseAddr);
21590 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21592 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21595 assert((Factor == 2 || Factor == 4) &&
21596 "expected interleave factor of 2 or 4 for MVE");
21598 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21599 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21600 Type *Tys[] = {VecTy, PtrTy};
21603 Ops.push_back(BaseAddr);
21604 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21614 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21618 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21619 VecTy->getNumElements() * Factor);
21625 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21627 unsigned Index = Indices[i];
21629 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21633 SubVec = Builder.CreateIntToPtr(
21637 SubVecs[SV].push_back(SubVec);
21646 auto &SubVec = SubVecs[SVI];
21649 SVI->replaceAllUsesWith(WideVec);
21685 const APInt &GapMask)
const {
21687 "Invalid interleave factor");
21692 "Unexpected mask on store");
21695 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21697 unsigned LaneLen = VecTy->getNumElements() / Factor;
21698 Type *EltTy = VecTy->getElementType();
21702 Align Alignment =
SI->getAlign();
21719 Type *IntTy =
DL.getIntPtrType(EltTy);
21724 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21725 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21731 Value *BaseAddr =
SI->getPointerOperand();
21733 if (NumStores > 1) {
21736 LaneLen /= NumStores;
21746 if (Subtarget->hasNEON()) {
21747 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21748 Intrinsic::arm_neon_vst3,
21749 Intrinsic::arm_neon_vst4};
21750 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21751 Type *Tys[] = {PtrTy, SubVecTy};
21754 Ops.push_back(BaseAddr);
21756 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21757 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21759 assert((Factor == 2 || Factor == 4) &&
21760 "expected interleave factor of 2 or 4 for MVE");
21762 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21763 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21764 Type *Tys[] = {PtrTy, SubVecTy};
21767 Ops.push_back(BaseAddr);
21769 for (
unsigned F = 0;
F < Factor;
F++) {
21770 Ops.push_back(Builder.getInt32(
F));
21771 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21777 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21780 if (StoreCount > 0)
21781 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21782 BaseAddr, LaneLen * Factor);
21787 for (
unsigned i = 0; i < Factor; i++) {
21788 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21789 if (Mask[IdxI] >= 0) {
21790 Shuffles.
push_back(Builder.CreateShuffleVector(
21793 unsigned StartMask = 0;
21794 for (
unsigned j = 1; j < LaneLen; j++) {
21795 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21796 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21797 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21807 Shuffles.
push_back(Builder.CreateShuffleVector(
21828 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21832 Members += SubMembers;
21838 Members += SubMembers * AT->getNumElements();
21839 }
else if (Ty->isFloatTy()) {
21844 }
else if (Ty->isDoubleTy()) {
21856 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21858 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21860 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21873 return (Members > 0 && Members <= 4);
21879 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21881 return ABITypeAlign;
21886 assert(StackAlign &&
"data layout string is missing stack alignment");
21887 return std::min(ABITypeAlign, *StackAlign);
21896 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21905 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
21906 return IsHA || IsIntArray;
21910 const Constant *PersonalityFn)
const {
21918 const Constant *PersonalityFn)
const {
21931void ARMTargetLowering::insertCopiesSplitCSR(
21935 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21945 RC = &ARM::GPRRegClass;
21946 else if (ARM::DPRRegClass.
contains(*
I))
21947 RC = &ARM::DPRRegClass;
21957 assert(Entry->getParent()->getFunction().hasFnAttribute(
21958 Attribute::NoUnwind) &&
21959 "Function should be nounwind in insertCopiesSplitCSR!");
21960 Entry->addLiveIn(*
I);
21965 for (
auto *Exit : Exits)
21967 TII->get(TargetOpcode::COPY), *
I)
21978 return Subtarget->hasMVEIntegerOps();
21988 unsigned NumElements = VTy->getNumElements();
21995 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
21996 return Subtarget->hasMVEFloatOps();
22001 return Subtarget->hasMVEIntegerOps() &&
22002 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22003 ScalarTy->isIntegerTy(32));
22013 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22015 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22017 if (TyWidth > 128) {
22018 int Stride = Ty->getNumElements() / 2;
22022 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22024 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22025 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22026 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22027 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22028 Value *LowerSplitAcc =
nullptr;
22029 Value *UpperSplitAcc =
nullptr;
22032 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22033 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22037 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22039 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22041 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22042 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22049 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22052 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22054 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22055 {ConstRotation, InputB, InputA});
22060 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22063 ConstRotation = ConstantInt::get(IntTy, 0);
22065 ConstRotation = ConstantInt::get(IntTy, 1);
22067 if (!ConstRotation)
22070 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22071 {ConstHalving, ConstRotation, InputA, InputB});
unsigned const MachineRegisterInfo * MRI
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool isNegatedInteger(SDValue Op)
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue LowerUADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue ConvertBooleanCarryToCarryFlag(SDValue BoolCarry, SelectionDAG &DAG)
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue ConvertCarryFlagToBooleanCarry(SDValue Flags, EVT VT, SelectionDAG &DAG)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static unsigned SelectPairHalf(unsigned Elements, ArrayRef< int > Mask, unsigned Index)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerTruncate(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformHWLoopCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, Value *Offset, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, Value *Offset, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned int Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first 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 SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
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)