83#include "llvm/IR/IntrinsicsARM.h"
118#define DEBUG_TYPE "arm-isel"
121STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
122STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
124 "Number of constants with their storage promoted into constant pools");
128 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
133 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
138 cl::desc(
"Maximum size of constant to promote into a constant pool"),
142 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
147 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
152 cl::desc(
"Maximum number of base-updates to check generating postindex."),
160 ARM::R0, ARM::R1, ARM::R2, ARM::R3
174void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
175 if (VT != PromotedLdStVT) {
184 if (ElemTy != MVT::f64)
188 if (ElemTy == MVT::i32) {
232void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
234 addTypeForNEON(VT, MVT::f64);
237void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
239 addTypeForNEON(VT, MVT::v2f64);
242void ARMTargetLowering::setAllExpand(
MVT VT) {
255void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
262void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
263 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
265 for (
auto VT : IntTypes) {
339 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
340 for (
auto VT : FloatTypes) {
414 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
415 for (
auto VT : LongTypes) {
432 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
433 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
434 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
451 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
460 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
461 for (
auto VT : pTypes) {
512 RegInfo(Subtarget->getRegisterInfo()),
513 Itins(Subtarget->getInstrItineraryData()) {
519 const Triple &TT = TM.getTargetTriple();
521 if (TT.isOSBinFormatMachO()) {
523 if (Subtarget->isThumb() && Subtarget->hasVFP2Base() &&
524 Subtarget->hasARMOps() && !Subtarget->useSoftFloat()) {
526 static const struct {
527 const RTLIB::Libcall
Op;
528 const RTLIB::LibcallImpl Impl;
531 { RTLIB::ADD_F32, RTLIB::impl___addsf3vfp },
532 { RTLIB::SUB_F32, RTLIB::impl___subsf3vfp },
533 { RTLIB::MUL_F32, RTLIB::impl___mulsf3vfp },
534 { RTLIB::DIV_F32, RTLIB::impl___divsf3vfp },
537 { RTLIB::ADD_F64, RTLIB::impl___adddf3vfp },
538 { RTLIB::SUB_F64, RTLIB::impl___subdf3vfp },
539 { RTLIB::MUL_F64, RTLIB::impl___muldf3vfp },
540 { RTLIB::DIV_F64, RTLIB::impl___divdf3vfp },
543 { RTLIB::OEQ_F32, RTLIB::impl___eqsf2vfp },
544 { RTLIB::UNE_F32, RTLIB::impl___nesf2vfp },
545 { RTLIB::OLT_F32, RTLIB::impl___ltsf2vfp },
546 { RTLIB::OLE_F32, RTLIB::impl___lesf2vfp },
547 { RTLIB::OGE_F32, RTLIB::impl___gesf2vfp },
548 { RTLIB::OGT_F32, RTLIB::impl___gtsf2vfp },
549 { RTLIB::UO_F32, RTLIB::impl___unordsf2vfp },
552 { RTLIB::OEQ_F64, RTLIB::impl___eqdf2vfp },
553 { RTLIB::UNE_F64, RTLIB::impl___nedf2vfp },
554 { RTLIB::OLT_F64, RTLIB::impl___ltdf2vfp },
555 { RTLIB::OLE_F64, RTLIB::impl___ledf2vfp },
556 { RTLIB::OGE_F64, RTLIB::impl___gedf2vfp },
557 { RTLIB::OGT_F64, RTLIB::impl___gtdf2vfp },
558 { RTLIB::UO_F64, RTLIB::impl___unorddf2vfp },
563 { RTLIB::FPTOSINT_F64_I32, RTLIB::impl___fixdfsivfp },
564 { RTLIB::FPTOUINT_F64_I32, RTLIB::impl___fixunsdfsivfp },
565 { RTLIB::FPTOSINT_F32_I32, RTLIB::impl___fixsfsivfp },
566 { RTLIB::FPTOUINT_F32_I32, RTLIB::impl___fixunssfsivfp },
569 { RTLIB::FPROUND_F64_F32, RTLIB::impl___truncdfsf2vfp },
570 { RTLIB::FPEXT_F32_F64, RTLIB::impl___extendsfdf2vfp },
577 { RTLIB::SINTTOFP_I32_F64, RTLIB::impl___floatsidfvfp },
578 { RTLIB::UINTTOFP_I32_F64, RTLIB::impl___floatunssidfvfp },
579 { RTLIB::SINTTOFP_I32_F32, RTLIB::impl___floatsisfvfp },
580 { RTLIB::UINTTOFP_I32_F32, RTLIB::impl___floatunssisfvfp },
584 for (
const auto &LC : LibraryCalls)
589 if (Subtarget->isThumb1Only())
594 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
595 Subtarget->hasFPRegs()) {
604 if (!Subtarget->hasVFP2Base()) {
605 setAllExpand(MVT::f32);
611 if (!Subtarget->hasFP64()) {
612 setAllExpand(MVT::f64);
620 if (Subtarget->hasFullFP16()) {
629 if (Subtarget->hasBF16()) {
631 setAllExpand(MVT::bf16);
632 if (!Subtarget->hasFullFP16())
644 addAllExtLoads(VT, InnerVT,
Expand);
653 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
656 if (!Subtarget->hasV8_1MMainlineOps())
659 if (!Subtarget->isThumb1Only())
668 if (Subtarget->hasMVEIntegerOps())
669 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
672 if (Subtarget->hasLOB()) {
676 if (Subtarget->hasNEON()) {
677 addDRTypeForNEON(MVT::v2f32);
678 addDRTypeForNEON(MVT::v8i8);
679 addDRTypeForNEON(MVT::v4i16);
680 addDRTypeForNEON(MVT::v2i32);
681 addDRTypeForNEON(MVT::v1i64);
683 addQRTypeForNEON(MVT::v4f32);
684 addQRTypeForNEON(MVT::v2f64);
685 addQRTypeForNEON(MVT::v16i8);
686 addQRTypeForNEON(MVT::v8i16);
687 addQRTypeForNEON(MVT::v4i32);
688 addQRTypeForNEON(MVT::v2i64);
690 if (Subtarget->hasFullFP16()) {
691 addQRTypeForNEON(MVT::v8f16);
692 addDRTypeForNEON(MVT::v4f16);
695 if (Subtarget->hasBF16()) {
696 addQRTypeForNEON(MVT::v8bf16);
697 addDRTypeForNEON(MVT::v4bf16);
701 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
741 if (Subtarget->hasNEON()) {
782 ISD::FRINT, ISD::FTRUNC, ISD::FROUNDEVEN}) {
854 if (!Subtarget->hasVFP4Base()) {
863 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
872 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
881 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
889 if (Subtarget->hasMVEIntegerOps()) {
894 if (Subtarget->hasMVEFloatOps()) {
898 if (!Subtarget->hasFP64()) {
943 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
946 if (Subtarget->hasFullFP16()) {
952 if (!Subtarget->hasFP16()) {
978 if (!Subtarget->isThumb1Only()) {
1003 if (Subtarget->hasDSP()) {
1013 if (Subtarget->hasBaseDSP()) {
1021 if (Subtarget->isThumb1Only()) {
1025 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
1026 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1041 if (Subtarget->hasMVEIntegerOps())
1045 if (Subtarget->isThumb1Only()) {
1051 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1065 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1074 if (Subtarget->hasPerfMon())
1078 if (!Subtarget->hasV6Ops())
1081 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1082 : Subtarget->hasDivideInARMMode();
1089 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1101 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1102 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1105 HasStandaloneRem =
false;
1132 if (TT.isOSWindows())
1139 InsertFencesForAtomic =
false;
1140 if (Subtarget->hasAnyDataBarrier() &&
1141 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1145 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1150 if (!Subtarget->hasAcquireRelease() ||
1153 InsertFencesForAtomic =
true;
1159 if (Subtarget->hasDataBarrier())
1160 InsertFencesForAtomic =
true;
1180 if (!InsertFencesForAtomic) {
1187 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1199 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1200 Subtarget->hasForced32BitAtomics()) {
1214 if (!Subtarget->hasV6Ops()) {
1220 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1221 !Subtarget->isThumb1Only()) {
1250 if (Subtarget->hasFullFP16()) {
1260 if (Subtarget->hasFullFP16())
1275 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1276 !Subtarget->isThumb1Only()) {
1283 if (!Subtarget->hasVFP4Base()) {
1289 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1291 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1299 if (!Subtarget->hasFP16()) {
1319 if (Subtarget->hasFPARMv8Base()) {
1329 if (Subtarget->hasNEON()) {
1336 if (Subtarget->hasFP64()) {
1351 if (Subtarget->hasFullFP16()) {
1357 ISD::FCOS, ISD::FSIN, ISD::FSINCOS,
1358 ISD::FSINCOSPI, ISD::FMODF, ISD::FACOS,
1359 ISD::FASIN, ISD::FATAN, ISD::FATAN2,
1360 ISD::FCOSH, ISD::FSINH, ISD::FTANH,
1361 ISD::FTAN, ISD::FEXP, ISD::FEXP2,
1362 ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
1378 for (
auto Op : {ISD::FROUND, ISD::FROUNDEVEN, ISD::FTRUNC,
1379 ISD::FNEARBYINT, ISD::FRINT, ISD::FFLOOR,
1388 if (Subtarget->hasNEON()) {
1400 if (Subtarget->hasV8Ops()) {
1415 if (Subtarget->hasFullFP16()) {
1443 if (TT.isOSWindows()) {
1460 if (Subtarget->hasMVEIntegerOps())
1463 if (Subtarget->hasV6Ops())
1465 if (Subtarget->isThumb1Only())
1468 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1469 Subtarget->isThumb2()) {
1475 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1476 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1498 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1504 return Subtarget->useSoftFloat();
1508 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1521std::pair<const TargetRegisterClass *, uint8_t>
1532 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1533 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1534 RRC = &ARM::DPRRegClass;
1539 if (Subtarget->useNEONForSinglePrecisionFP())
1542 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1543 case MVT::v4f32:
case MVT::v2f64:
1544 RRC = &ARM::DPRRegClass;
1548 RRC = &ARM::DPRRegClass;
1552 RRC = &ARM::DPRRegClass;
1556 return std::make_pair(RRC,
Cost);
1560#define MAKE_CASE(V) \
1779 if ((Subtarget->hasMVEIntegerOps() &&
1780 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1781 VT == MVT::v16i8)) ||
1782 (Subtarget->hasMVEFloatOps() &&
1783 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1797 if (Subtarget->hasNEON()) {
1798 if (VT == MVT::v4i64)
1799 return &ARM::QQPRRegClass;
1800 if (VT == MVT::v8i64)
1801 return &ARM::QQQQPRRegClass;
1803 if (Subtarget->hasMVEIntegerOps()) {
1804 if (VT == MVT::v4i64)
1805 return &ARM::MQQPRRegClass;
1806 if (VT == MVT::v8i64)
1807 return &ARM::MQQQQPRRegClass;
1816 Align &PrefAlign)
const {
1823 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1835 unsigned NumVals =
N->getNumValues();
1839 for (
unsigned i = 0; i != NumVals; ++i) {
1840 EVT VT =
N->getValueType(i);
1841 if (VT == MVT::Glue || VT == MVT::Other)
1847 if (!
N->isMachineOpcode())
1855 if (
MCID.getNumDefs() == 0)
1857 if (!Itins->isEmpty() &&
1858 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1872 return Const->getZExtValue() == 16;
1880 return Const->getZExtValue() == 16;
1888 return Const->getZExtValue() == 16;
1957 bool isVarArg)
const {
1976 if (!
getTM().isAAPCS_ABI())
1978 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1986 if (!
getTM().isAAPCS_ABI()) {
1987 if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() && !isVarArg)
1990 }
else if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() &&
1999 bool isVarArg)
const {
2000 return CCAssignFnForNode(CC,
false, isVarArg);
2004 bool isVarArg)
const {
2005 return CCAssignFnForNode(CC,
true, isVarArg);
2012 bool isVarArg)
const {
2013 switch (getEffectiveCallingConv(CC, isVarArg)) {
2039 if (Subtarget->hasFullFP16()) {
2044 Val = DAG.
getNode(ISD::BITCAST, dl, ValVT, Val);
2052 if (Subtarget->hasFullFP16()) {
2056 Val = DAG.
getNode(ISD::BITCAST, dl,
2061 return DAG.
getNode(ISD::BITCAST, dl, LocVT, Val);
2066SDValue ARMTargetLowering::LowerCallResult(
2070 SDValue ThisVal,
bool isCmseNSCall)
const {
2078 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
2079 CCValAssign VA = RVLocs[i];
2083 if (i == 0 && isThisReturn) {
2085 "unexpected return calling convention register assignment");
2103 if (!Subtarget->isLittle())
2120 if (!Subtarget->isLittle())
2163std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
2165 bool IsTailCall,
int SPDiff)
const {
2167 MachinePointerInfo DstInfo;
2187 return std::make_pair(DstAddr, DstInfo);
2196ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
2209 if (!SrcFrameIdxNode || !DstFrameIdxNode)
2212 int SrcFI = SrcFrameIdxNode->getIndex();
2213 int DstFI = DstFrameIdxNode->getIndex();
2215 "byval passed in non-fixed stack slot");
2237 if (SrcOffset == DstOffset)
2245 RegsToPassVector &RegsToPass,
2252 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
2253 unsigned id = Subtarget->isLittle() ? 0 : 1;
2265 MachinePointerInfo DstInfo;
2266 std::tie(DstAddr, DstInfo) =
2267 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2284 SelectionDAG &DAG = CLI.
DAG;
2286 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2287 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2288 SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2295 const CallBase *CB = CLI.
CB;
2298 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2300 MachineFunction::CallSiteInfo CSInfo;
2301 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2302 bool isThisReturn =
false;
2303 bool isCmseNSCall =
false;
2304 bool isSibCall =
false;
2305 bool PreferIndirect =
false;
2306 bool GuardWithBTI =
false;
2316 !Subtarget->noBTIAtReturnTwice())
2321 CSInfo = MachineFunction::CallSiteInfo(*CB);
2325 isCmseNSCall =
true;
2328 if (!Subtarget->supportsTailCall())
2344 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2345 count_if(GV->users(), [&BB](
const User *U) {
2346 return isa<Instruction>(U) &&
2347 cast<Instruction>(U)->getParent() == BB;
2354 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2368 "site marked musttail");
2371 unsigned NumBytes = CCInfo.getStackSize();
2380 if (isTailCall && !isSibCall) {
2381 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2382 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2387 assert(StackAlign &&
"data layout string is missing stack alignment");
2388 NumBytes =
alignTo(NumBytes, *StackAlign);
2393 SPDiff = NumReusableBytes - NumBytes;
2397 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2413 RegsToPassVector RegsToPass;
2422 DenseMap<unsigned, SDValue> ByValTemporaries;
2426 for (
const CCValAssign &VA : ArgLocs) {
2428 SDValue Src = OutVals[ArgIdx];
2429 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2431 if (!
Flags.isByVal())
2435 MachinePointerInfo DstInfo;
2436 std::tie(Dst, DstInfo) =
2437 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2438 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2440 if (Copy == NoCopy) {
2445 }
else if (Copy == CopyOnce) {
2449 ByValTemporaries[ArgIdx] = Src;
2451 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2455 int TempFrameIdx = MFI.CreateStackObject(
2456 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2464 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2465 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2468 ByValTemporaries[ArgIdx] = Temp;
2471 if (!ByValCopyChains.
empty())
2481 bool AfterFormalArgLoads =
false;
2485 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2487 ++i, ++realArgIdx) {
2488 CCValAssign &VA = ArgLocs[i];
2489 SDValue Arg = OutVals[realArgIdx];
2490 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2491 bool isByVal =
Flags.isByVal();
2511 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2516 AfterFormalArgLoads =
true;
2528 auto ArgVT = Outs[realArgIdx].ArgVT;
2529 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2547 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2548 StackPtr, MemOpChains, isTailCall, SPDiff);
2552 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2553 StackPtr, MemOpChains, isTailCall, SPDiff);
2557 MachinePointerInfo DstInfo;
2558 std::tie(DstAddr, DstInfo) =
2559 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2563 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2564 StackPtr, MemOpChains, isTailCall, SPDiff);
2566 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2567 Outs[0].VT == MVT::i32) {
2569 "unexpected calling convention register assignment");
2570 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2571 "unexpected use of 'returned'");
2572 isThisReturn =
true;
2577 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2578 }
else if (isByVal) {
2580 unsigned offset = 0;
2584 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2585 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2588 bool NeedsStackCopy;
2589 if (
auto It = ByValTemporaries.
find(realArgIdx);
2590 It != ByValTemporaries.
end()) {
2591 ByValSrc = It->second;
2592 NeedsStackCopy =
true;
2595 NeedsStackCopy = !isTailCall;
2599 if (CurByValIdx < ByValArgsCount) {
2600 unsigned RegBegin, RegEnd;
2601 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2605 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2609 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2612 RegsToPass.push_back(std::make_pair(j, Load));
2617 offset = RegEnd - RegBegin;
2619 CCInfo.nextInRegsParam();
2624 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2627 MachinePointerInfo DstInfo;
2628 std::tie(Dst, DstInfo) =
2629 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2637 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2638 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2645 MachinePointerInfo DstInfo;
2646 std::tie(DstAddr, DstInfo) =
2647 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2654 if (!MemOpChains.
empty())
2660 for (
const auto &[
Reg,
N] : RegsToPass) {
2668 bool isDirect =
false;
2671 const GlobalValue *GVal =
nullptr;
2673 GVal =
G->getGlobal();
2674 bool isStub = !TM.shouldAssumeDSOLocal(GVal) && Subtarget->isTargetMachO();
2676 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2677 bool isLocalARMFunc =
false;
2680 if (Subtarget->genLongCalls()) {
2682 "long-calls codegen is not position independent!");
2687 if (Subtarget->genExecuteOnly()) {
2688 if (Subtarget->useMovt())
2706 const char *Sym = S->getSymbol();
2708 if (Subtarget->genExecuteOnly()) {
2709 if (Subtarget->useMovt())
2728 if (!PreferIndirect) {
2733 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2735 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2736 assert(Subtarget->isTargetMachO() &&
"WrapperPIC use on non-MachO?");
2745 }
else if (Subtarget->isTargetCOFF()) {
2746 assert(Subtarget->isTargetWindows() &&
2747 "Windows is the only supported COFF target");
2751 else if (!TM.shouldAssumeDSOLocal(GVal))
2767 const char *Sym = S->getSymbol();
2768 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2770 ARMConstantPoolValue *CPV =
2772 ARMPCLabelIndex, 4);
2786 assert(!isARMFunc && !isDirect &&
2787 "Cannot handle call to ARM function or direct call");
2791 "call to non-secure function would require "
2792 "passing arguments on stack",
2798 "call to non-secure function would return value through pointer",
2805 if (Subtarget->isThumb()) {
2808 else if (isCmseNSCall)
2810 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2815 if (!isDirect && !Subtarget->hasV5TOps())
2817 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2819 !Subtarget->hasMinSize())
2830 if (isTailCall && !isSibCall) {
2835 std::vector<SDValue>
Ops;
2836 Ops.push_back(Chain);
2837 Ops.push_back(Callee);
2845 for (
const auto &[
Reg,
N] : RegsToPass)
2849 const uint32_t *
Mask;
2850 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2858 isThisReturn =
false;
2864 assert(Mask &&
"Missing call preserved mask for calling convention");
2868 Ops.push_back(InGlue);
2881 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2892 uint64_t CalleePopBytes =
2895 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2901 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2902 InVals, isThisReturn,
2903 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2910void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2911 Align Alignment)
const {
2913 Alignment = std::max(Alignment,
Align(4));
2919 unsigned AlignInRegs = Alignment.
value() / 4;
2920 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2921 for (
unsigned i = 0; i < Waste; ++i)
2927 unsigned Excess = 4 * (ARM::R4 -
Reg);
2934 if (NSAAOffset != 0 &&
Size > Excess) {
2946 unsigned ByValRegBegin =
Reg;
2947 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2951 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2957 Size = std::max<int>(
Size - Excess, 0);
2965bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2971 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2972 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2973 const SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2974 const SelectionDAG &DAG = CLI.
DAG;
2979 assert(Subtarget->supportsTailCall());
2992 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2994 if (!(Subtarget->isThumb1Only() ||
2995 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2996 AddressRegisters.
insert(ARM::R12);
2997 for (
const CCValAssign &AL : ArgLocs)
2999 AddressRegisters.
erase(
AL.getLocReg());
3000 if (AddressRegisters.
empty()) {
3001 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
3020 <<
" (guaranteed tail-call CC)\n");
3021 return CalleeCC == CallerCC;
3026 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
3028 if (isCalleeStructRet != isCallerStructRet) {
3041 const GlobalValue *GV =
G->getGlobal();
3044 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
3045 TT.isOSBinFormatMachO())) {
3054 getEffectiveCallingConv(CalleeCC, isVarArg),
3055 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
3062 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3063 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
3064 if (CalleeCC != CallerCC) {
3065 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
3066 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
3075 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
3085 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
3104 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
3113 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
3126 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
3129 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
3133 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
3160 bool isLittleEndian = Subtarget->isLittle();
3163 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3172 "secure entry function would return value through pointer",
3177 for (
unsigned i = 0, realRVLocIdx = 0;
3179 ++i, ++realRVLocIdx) {
3180 CCValAssign &VA = RVLocs[i];
3183 SDValue Arg = OutVals[realRVLocIdx];
3184 bool ReturnF16 =
false;
3186 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
3219 auto RetVT = Outs[realRVLocIdx].ArgVT;
3241 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3245 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3251 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3263 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3265 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3270 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3280 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3306 !Subtarget->isMClass()) {
3307 if (Subtarget->isThumb1Only())
3314 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3317bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3318 if (
N->getNumValues() != 1)
3320 if (!
N->hasNUsesOfValue(1, 0))
3324 SDNode *
Copy = *
N->user_begin();
3328 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3330 TCChain =
Copy->getOperand(0);
3332 SDNode *VMov =
Copy;
3334 SmallPtrSet<SDNode*, 2>
Copies;
3335 for (SDNode *U : VMov->
users()) {
3343 for (SDNode *U : VMov->
users()) {
3344 SDValue UseChain =
U->getOperand(0);
3352 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3358 }
else if (
Copy->getOpcode() == ISD::BITCAST) {
3360 if (!
Copy->hasOneUse())
3367 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3369 TCChain =
Copy->getOperand(0);
3374 bool HasRet =
false;
3375 for (
const SDNode *U :
Copy->users()) {
3389bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3390 if (!Subtarget->supportsTailCall())
3407 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3423 EVT PtrVT =
Op.getValueType();
3433 if (Subtarget->genExecuteOnly()) {
3435 auto *
T =
CP->getType();
3436 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3438 auto GV =
new GlobalVariable(
3446 return LowerGlobalAddress(GA, DAG);
3451 Align CPAlign =
CP->getAlign();
3452 if (Subtarget->isThumb1Only())
3453 CPAlign = std::max(CPAlign,
Align(4));
3454 if (
CP->isMachineConstantPoolEntry())
3466 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3475 unsigned ARMPCLabelIndex = 0;
3481 if (!IsPositionIndependent) {
3484 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3495 if (!IsPositionIndependent)
3526ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3528 assert(Subtarget->isTargetDarwin() &&
3529 "This function expects a Darwin target");
3534 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3540 MVT::i32,
DL, Chain, DescAddr,
3555 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3564 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3570ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3572 assert(Subtarget->isTargetWindows() &&
"Windows specific TLS lowering");
3596 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3605 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3611 MachinePointerInfo());
3631 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3633 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3635 ARMConstantPoolValue *CPV =
3653 TargetLowering::CallLoweringInfo CLI(DAG);
3658 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3659 return CallResult.first;
3668 const GlobalValue *GV = GA->
getGlobal();
3678 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3681 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3682 ARMConstantPoolValue *CPV =
3689 PtrVT, dl, Chain,
Offset,
3697 PtrVT, dl, Chain,
Offset,
3702 ARMConstantPoolValue *CPV =
3707 PtrVT, dl, Chain,
Offset,
3722 if (Subtarget->isTargetDarwin())
3723 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3725 if (Subtarget->isTargetWindows())
3726 return LowerGlobalTLSAddressWindows(
Op, DAG);
3729 assert(Subtarget->isTargetELF() &&
"Only ELF implemented here");
3735 return LowerToTLSGeneralDynamicModel(GA, DAG);
3738 return LowerToTLSExecModels(GA, DAG, model);
3747 while (!Worklist.
empty()) {
3755 if (!
I ||
I->getParent()->getParent() !=
F)
3784 if (!GVar || !GVar->hasInitializer() ||
3785 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3786 !GVar->hasLocalLinkage())
3791 auto *
Init = GVar->getInitializer();
3793 Init->needsDynamicRelocation())
3805 unsigned RequiredPadding = 4 - (
Size % 4);
3806 bool PaddingPossible =
3807 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3812 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3836 if (RequiredPadding != 4) {
3841 while (RequiredPadding--)
3853 ++NumConstpoolPromoted;
3859 if (!(GV = GA->getAliaseeObject()))
3862 return V->isConstant();
3871 return LowerGlobalAddressWindows(
Op, DAG);
3873 return LowerGlobalAddressELF(
Op, DAG);
3875 return LowerGlobalAddressDarwin(
Op, DAG);
3887 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3900 }
else if (Subtarget->isROPI() && IsRO) {
3905 }
else if (Subtarget->isRWPI() && !IsRO) {
3908 if (Subtarget->useMovt()) {
3913 ARMConstantPoolValue *CPV =
3930 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3931 if (Subtarget->useMovt())
3948 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3949 "ROPI/RWPI not currently supported for Darwin");
3954 if (Subtarget->useMovt())
3965 if (Subtarget->isGVIndirectSymbol(GV))
3973 assert(Subtarget->isTargetWindows() &&
"non-Windows COFF is not supported");
3974 assert(Subtarget->useMovt() &&
3975 "Windows on ARM expects to use movw/movt");
3976 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3977 "ROPI/RWPI not currently supported for Windows");
3984 else if (!TM.shouldAssumeDSOLocal(GV))
4008 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
4009 Op.getOperand(1), Val);
4026SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
4029 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
4033 case Intrinsic::arm_gnu_eabi_mcount: {
4039 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
4040 const uint32_t *
Mask =
4042 assert(Mask &&
"Missing call preserved mask for calling convention");
4047 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
4051 if (Subtarget->isThumb())
4054 ARM::tBL_PUSHLR, dl, ResultTys,
4055 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
4056 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
4060 {ReturnAddress, Callee, RegisterMask, Chain}),
4069 unsigned IntNo =
Op.getConstantOperandVal(0);
4073 case Intrinsic::thread_pointer: {
4077 case Intrinsic::arm_cls: {
4078 const SDValue &Operand =
Op.getOperand(1);
4079 const EVT VTy =
Op.getValueType();
4090 case Intrinsic::arm_cls64: {
4093 const SDValue &Operand =
Op.getOperand(1);
4094 const EVT VTy =
Op.getValueType();
4117 case Intrinsic::eh_sjlj_lsda: {
4119 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4124 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
4125 ARMConstantPoolValue *CPV =
4134 if (IsPositionIndependent) {
4140 case Intrinsic::arm_neon_vabs:
4143 case Intrinsic::arm_neon_vabds:
4144 if (
Op.getValueType().isInteger())
4146 Op.getOperand(1),
Op.getOperand(2));
4148 case Intrinsic::arm_neon_vabdu:
4150 Op.getOperand(1),
Op.getOperand(2));
4151 case Intrinsic::arm_neon_vmulls:
4152 case Intrinsic::arm_neon_vmullu: {
4153 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
4155 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4156 Op.getOperand(1),
Op.getOperand(2));
4158 case Intrinsic::arm_neon_vminnm:
4159 case Intrinsic::arm_neon_vmaxnm: {
4160 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
4161 ? ISD::FMINNUM : ISD::FMAXNUM;
4162 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4163 Op.getOperand(1),
Op.getOperand(2));
4165 case Intrinsic::arm_neon_vminu:
4166 case Intrinsic::arm_neon_vmaxu: {
4167 if (
Op.getValueType().isFloatingPoint())
4169 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
4171 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4172 Op.getOperand(1),
Op.getOperand(2));
4174 case Intrinsic::arm_neon_vmins:
4175 case Intrinsic::arm_neon_vmaxs: {
4177 if (!
Op.getValueType().isFloatingPoint()) {
4178 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4180 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4181 Op.getOperand(1),
Op.getOperand(2));
4183 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4184 ? ISD::FMINIMUM : ISD::FMAXIMUM;
4185 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4186 Op.getOperand(1),
Op.getOperand(2));
4188 case Intrinsic::arm_neon_vtbl1:
4190 Op.getOperand(1),
Op.getOperand(2));
4191 case Intrinsic::arm_neon_vtbl2:
4193 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4194 case Intrinsic::arm_mve_pred_i2v:
4195 case Intrinsic::arm_mve_pred_v2i:
4198 case Intrinsic::arm_mve_vreinterpretq:
4201 case Intrinsic::arm_mve_lsll:
4203 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4204 case Intrinsic::arm_mve_asrl:
4206 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4217 if (!Subtarget->hasDataBarrier()) {
4221 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4222 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4233 }
else if (Subtarget->preferISHSTBarriers() &&
4242 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4250 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4252 return Op.getOperand(0);
4255 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4257 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4259 return Op.getOperand(0);
4261 unsigned isData =
Op.getConstantOperandVal(4);
4262 if (Subtarget->isThumb()) {
4264 isRead = ~isRead & 1;
4265 isData = ~isData & 1;
4283 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4291 const SDLoc &dl)
const {
4293 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4295 const TargetRegisterClass *RC;
4297 RC = &ARM::tGPRRegClass;
4299 RC = &ARM::GPRRegClass;
4313 MVT::i32, dl, Root, FIN,
4319 if (!Subtarget->isLittle())
4334 const Value *OrigArg,
4335 unsigned InRegsParamRecordIdx,
4336 int ArgOffset,
unsigned ArgSize)
const {
4350 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4351 unsigned RBegin, REnd;
4356 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4361 ArgOffset = -4 * (ARM::R4 - RBegin);
4368 const TargetRegisterClass *RC =
4371 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4375 MachinePointerInfo(OrigArg, 4 * i));
4380 if (!MemOps.
empty())
4389 unsigned TotalArgRegsSaveSize,
4390 bool ForceMutable)
const {
4392 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4401 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4405bool ARMTargetLowering::splitValueIntoRegisterParts(
4407 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4409 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4414 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
4421SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4423 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4424 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4431 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
4437SDValue ARMTargetLowering::LowerFormalArguments(
4444 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4453 unsigned CurArgIdx = 0;
4465 unsigned ArgRegBegin = ARM::R4;
4466 for (
const CCValAssign &VA : ArgLocs) {
4472 if (!
Flags.isByVal())
4476 unsigned RBegin, REnd;
4478 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4484 int lastInsIndex = -1;
4488 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4491 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4495 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4496 CCValAssign &VA = ArgLocs[i];
4497 if (Ins[VA.
getValNo()].isOrigArg()) {
4498 std::advance(CurOrigArg,
4499 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4511 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4518 MVT::f64, dl, Chain, FIN,
4521 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4529 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4531 const TargetRegisterClass *RC;
4533 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4534 RC = &ARM::HPRRegClass;
4535 else if (RegVT == MVT::f32)
4536 RC = &ARM::SPRRegClass;
4537 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4538 RegVT == MVT::v4bf16)
4539 RC = &ARM::DPRRegClass;
4540 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4541 RegVT == MVT::v8bf16)
4542 RC = &ARM::QPRRegClass;
4543 else if (RegVT == MVT::i32)
4545 : &ARM::GPRRegClass;
4591 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4597 if (index != lastInsIndex)
4599 ISD::ArgFlagsTy
Flags =
Ins[index].Flags;
4605 if (
Flags.isByVal()) {
4606 assert(Ins[index].isOrigArg() &&
4607 "Byval arguments cannot be implicit");
4611 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4645 lastInsIndex = index;
4652 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4653 TotalArgRegsSaveSize);
4657 "secure entry function must not be variadic", dl.
getDebugLoc()));
4667 assert(StackAlign &&
"data layout string is missing stack alignment");
4668 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4677 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4686 return CFP->getValueAPF().isPosZero();
4690 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4693 return CFP->getValueAPF().isPosZero();
4695 }
else if (
Op->getOpcode() == ISD::BITCAST &&
4696 Op->getValueType(0) == MVT::f64) {
4711 const SDLoc &dl)
const {
4713 unsigned C = RHSC->getZExtValue();
4777 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4781 unsigned Mask =
LHS.getConstantOperandVal(1);
4783 uint64_t RHSV = RHSC->getZExtValue();
4784 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4786 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4800 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4803 LHS.getConstantOperandVal(1) < 31) {
4804 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4847 bool Signaling)
const {
4848 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4863std::pair<SDValue, SDValue>
4866 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4878 switch (
Op.getOpcode()) {
4930 return std::make_pair(
Value, OverflowCmp);
4941 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4946 EVT VT =
Op.getValueType();
4951 SDVTList VTs = DAG.
getVTList(
Op.getValueType(), MVT::i32);
4989 EVT VT =
Op.getValueType();
4990 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4993 switch (
Op.getOpcode()) {
5018 EVT VT =
Op.getValueType();
5019 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
5029 switch (
Op->getOpcode()) {
5045 switch (
Op->getOpcode()) {
5064 DAG.
getNode(NewOpcode, dl, MVT::i32,
5075 unsigned Opc =
Cond.getOpcode();
5077 if (
Cond.getResNo() == 1 &&
5085 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5086 EVT VT =
Op.getValueType();
5088 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
5097 const ConstantSDNode *CMOVTrue =
5099 const ConstantSDNode *CMOVFalse =
5102 if (CMOVTrue && CMOVFalse) {
5108 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5110 False = SelectFalse;
5111 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5117 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5118 Cond.getOperand(3), DAG);
5133 bool &swpCmpOps,
bool &swpVselOps) {
5161 swpCmpOps = !swpCmpOps;
5162 swpVselOps = !swpVselOps;
5185 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5187 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5189 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5224 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5226 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5247 EVT VT =
Op.getValueType();
5269 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5282 int64_t PosVal = std::max(Val1, Val2);
5283 int64_t NegVal = std::min(Val1, Val2);
5330 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5335 if (*K != KTmp || V != VTmp)
5346bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5348 return !Subtarget->hasVFP2Base();
5350 return !Subtarget->hasFP64();
5352 return !Subtarget->hasFullFP16();
5357 EVT VT =
Op.getValueType();
5361 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5373 if (VT == MVT::i32 &&
5393 if (
Op.getValueType().isInteger()) {
5401 LHS.getValueType() ==
RHS.getValueType()) {
5402 EVT VT =
LHS.getValueType();
5408 Shift = DAG.
getNOT(dl, Shift, VT);
5414 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5415 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5418 unsigned Opcode = 0;
5420 if (TVal == ~FVal) {
5422 }
else if (TVal == ~FVal + 1) {
5424 }
else if (TVal + 1 == FVal) {
5426 }
else if (TVal == FVal + 1) {
5457 EVT VT =
TrueVal.getValueType();
5458 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5462 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5467 if (!
RHS.getNode()) {
5473 if (
LHS.getValueType() == MVT::i32) {
5484 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5485 TrueVal.getValueType() == MVT::f32 ||
5486 TrueVal.getValueType() == MVT::f64)) {
5500 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5510 if (Subtarget->hasFPARMv8Base() &&
5512 (
TrueVal.getValueType() == MVT::f16 ||
5513 TrueVal.getValueType() == MVT::f32 ||
5514 TrueVal.getValueType() == MVT::f64)) {
5515 bool swpCmpOps =
false;
5516 bool swpVselOps =
false;
5530 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5533 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5543 if (!
N->hasOneUse())
5546 if (!
N->getNumValues())
5548 EVT VT =
Op.getValueType();
5549 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5566 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5567 Ld->getPointerInfo(), Ld->getAlign(),
5568 Ld->getMemOperand()->getFlags());
5586 DAG.
getLoad(MVT::i32, dl, Ld->getChain(),
Ptr, Ld->getPointerInfo(),
5587 Ld->getAlign(), Ld->getMemOperand()->getFlags());
5589 EVT PtrType =
Ptr.getValueType();
5592 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5593 Ld->getPointerInfo().getWithOffset(4),
5595 Ld->getMemOperand()->getFlags());
5613 bool LHSSeenZero =
false;
5615 bool RHSSeenZero =
false;
5617 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5628 if (
LHS.getValueType() == MVT::f32) {
5646 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5674 unsigned Opc =
Cond.getOpcode();
5676 !Subtarget->isThumb1Only();
5677 if (
Cond.getResNo() == 1 &&
5687 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5693 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5710 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5715 if (!
RHS.getNode()) {
5723 unsigned Opc =
LHS.getOpcode();
5725 !Subtarget->isThumb1Only();
5737 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5744 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5751 if (
LHS.getValueType() == MVT::i32) {
5757 SDNodeFlags
Flags =
Op->getFlags();
5758 if (
Flags.hasNoNaNs() &&
5763 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5794 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5800 Addr,
Op.getOperand(2), JTI);
5804 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5811 DAG.
getLoad(PTy, dl, Chain, Addr,
5819 EVT VT =
Op.getValueType();
5822 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5823 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5831 const EVT OpTy =
Op.getOperand(0).getValueType();
5832 if (OpTy == MVT::v4f32)
5834 else if (OpTy == MVT::v4f16 && HasFullFP16)
5836 else if (OpTy == MVT::v8f16 && HasFullFP16)
5841 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5844 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5849 EVT VT =
Op.getValueType();
5853 bool IsStrict =
Op->isStrictFPOpcode();
5854 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5856 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5869 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5870 CallOptions, Loc, Chain);
5880 Loc,
Op.getValueType(), SrcVal);
5889 EVT VT =
Op.getValueType();
5891 EVT FromVT =
Op.getOperand(0).getValueType();
5893 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5895 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5896 Subtarget->hasFP64())
5898 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5899 Subtarget->hasFullFP16())
5901 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5902 Subtarget->hasMVEFloatOps())
5904 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5905 Subtarget->hasMVEFloatOps())
5908 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5925 EVT VT =
Op.getValueType();
5928 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5934 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5935 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5936 "Invalid type for custom lowering!");
5941 if (VT == MVT::v4f32)
5942 DestVecType = MVT::v4i32;
5943 else if (VT == MVT::v4f16 && HasFullFP16)
5944 DestVecType = MVT::v4i16;
5945 else if (VT == MVT::v8f16 && HasFullFP16)
5946 DestVecType = MVT::v8i16;
5952 switch (
Op.getOpcode()) {
5964 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5969 EVT VT =
Op.getValueType();
5972 if (isUnsupportedFloatingType(VT)) {
5982 CallOptions, SDLoc(
Op)).first;
5993 EVT VT =
Op.getValueType();
5995 bool InGPR = Tmp0.
getOpcode() == ISD::BITCAST ||
5997 bool UseNEON = !InGPR && Subtarget->hasNEON();
6004 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
6007 DAG.
getNode(ISD::BITCAST, dl, OpVT, Mask),
6011 if (SrcVT == MVT::f32) {
6015 DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1),
6017 }
else if (VT == MVT::f32)
6019 DAG.
getNode(ISD::BITCAST, dl, MVT::v1i64, Tmp1),
6021 Tmp0 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp0);
6022 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1);
6033 if (VT == MVT::f32) {
6034 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::v2f32, Res);
6038 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Res);
6045 if (SrcVT == MVT::f64)
6048 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp1);
6054 if (VT == MVT::f32) {
6056 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
6057 return DAG.
getNode(ISD::BITCAST, dl, MVT::f32,
6075 EVT VT =
Op.getValueType();
6077 unsigned Depth =
Op.getConstantOperandVal(0);
6079 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
6083 MachinePointerInfo());
6092 const ARMBaseRegisterInfo &ARI =
6093 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
6098 EVT VT =
Op.getValueType();
6100 unsigned Depth =
Op.getConstantOperandVal(0);
6105 MachinePointerInfo());
6113 return StringSwitch<Register>(
RegName)
6114 .Case(
"sp", ARM::SP)
6125 assert(
N->getValueType(0) == MVT::i64
6126 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6129 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6169 const APInt &APIntIndex = Index->getAPIntValue();
6171 NewIndex *= APIntIndex;
6183 SDValue BitCast = DAG.
getNode(ISD::BITCAST, dl, VecVT, ExtractSrc);
6200 EVT SrcVT =
Op.getValueType();
6201 EVT DstVT =
N->getValueType(0);
6203 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6204 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6205 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6208 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6209 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6210 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6217 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6228 return DAG.
getNode(ISD::BITCAST, dl, DstVT,
6262 return DAG.
getNode(ISD::BITCAST, dl, VT, Vmov);
6270 EVT VT =
Op.getValueType();
6313 EVT VT =
Op.getValueType();
6355 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6407 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6435 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6465 EVT VT =
N->getValueType(0);
6466 if (VT.
isVector() && ST->hasNEON()) {
6475 if (ElemTy == MVT::i8) {
6483 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6486 unsigned NumBits = ElemTy.getSizeInBits();
6498 if (ElemTy == MVT::i64) {
6511 if (!ST->hasV6T2Ops())
6520 EVT VT =
N->getValueType(0);
6523 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6524 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6525 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6526 "Unexpected type for custom ctpop lowering");
6534 unsigned EltSize = 8;
6556 while (
Op.getOpcode() == ISD::BITCAST)
6557 Op =
Op.getOperand(0);
6559 APInt SplatBits, SplatUndef;
6560 unsigned SplatBitSize;
6563 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6565 SplatBitSize > ElementBits)
6576 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6580 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6591 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6596 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6597 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6606 EVT VT =
N->getValueType(0);
6628 "unexpected vector shift opcode");
6630 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6631 unsigned VShiftOpc =
6633 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6639 EVT ShiftVT =
N->getOperand(1).getValueType();
6642 unsigned VShiftOpc =
6644 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6649 EVT VT =
N->getValueType(0);
6658 "Unknown shift to lower!");
6660 unsigned ShOpc =
N->getOpcode();
6661 if (ST->hasMVEIntegerOps()) {
6691 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6705 if (ST->isThumb1Only())
6710 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6726 bool Invert =
false;
6733 EVT VT =
Op.getValueType();
6741 assert(ST->hasMVEIntegerOps() &&
6742 "No hardware support for integer vector comparison!");
6744 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6767 Merged = DAG.
getNode(ISD::BITCAST, dl, CmpVT, Merged);
6769 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6779 switch (SetCCOpcode) {
6783 if (ST->hasMVEFloatOps()) {
6786 Invert =
true; [[fallthrough]];
6791 case ISD::SETLT: Swap =
true; [[fallthrough]];
6795 case ISD::SETLE: Swap =
true; [[fallthrough]];
6811 Result = DAG.
getNOT(dl, Result, VT);
6814 case ISD::SETUO: Invert =
true; [[fallthrough]];
6823 Result = DAG.
getNOT(dl, Result, VT);
6829 switch (SetCCOpcode) {
6832 if (ST->hasMVEIntegerOps()) {
6835 Invert =
true; [[fallthrough]];
6838 case ISD::SETLT: Swap =
true; [[fallthrough]];
6840 case ISD::SETLE: Swap =
true; [[fallthrough]];
6857 if (AndOp.getNode() && AndOp.getOpcode() == ISD::BITCAST)
6860 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6861 Op0 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(0));
6862 Op1 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(1));
6865 Result = DAG.
getNOT(dl, Result, VT);
6899 Result = DAG.
getNOT(dl, Result, VT);
6911 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6938 unsigned OpCmode, Imm;
6949 switch (SplatBitSize) {
6954 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6957 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6962 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6963 if ((SplatBits & ~0xff) == 0) {
6969 if ((SplatBits & ~0xff00) == 0) {
6972 Imm = SplatBits >> 8;
6982 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6983 if ((SplatBits & ~0xff) == 0) {
6989 if ((SplatBits & ~0xff00) == 0) {
6992 Imm = SplatBits >> 8;
6995 if ((SplatBits & ~0xff0000) == 0) {
6998 Imm = SplatBits >> 16;
7001 if ((SplatBits & ~0xff000000) == 0) {
7004 Imm = SplatBits >> 24;
7011 if ((SplatBits & ~0xffff) == 0 &&
7012 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
7015 Imm = SplatBits >> 8;
7023 if ((SplatBits & ~0xffffff) == 0 &&
7024 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
7027 Imm = SplatBits >> 16;
7043 unsigned ImmMask = 1;
7045 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
7046 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
7048 }
else if ((SplatBits & BitMask) != 0) {
7057 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
7071 EVT VT =
Op.getValueType();
7072 bool IsDouble = (VT == MVT::f64);
7078 if (
ST->genExecuteOnly()) {
7080 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
7081 "Unexpected architecture");
7104 if (!
ST->hasVFP3Base())
7109 if (IsDouble && !Subtarget->hasFP64())
7116 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7134 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7143 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7154 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
7171 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
7197 unsigned ExpectedElt = Imm;
7198 for (
unsigned i = 1; i < NumElts; ++i) {
7202 if (ExpectedElt == NumElts)
7205 if (M[i] < 0)
continue;
7206 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7214 bool &ReverseVEXT,
unsigned &Imm) {
7216 ReverseVEXT =
false;
7227 unsigned ExpectedElt = Imm;
7228 for (
unsigned i = 1; i < NumElts; ++i) {
7232 if (ExpectedElt == NumElts * 2) {
7237 if (M[i] < 0)
continue;
7238 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7253 return VT == MVT::v8i8 && M.size() == 8;
7258 if (Mask.size() == Elements * 2)
7259 return Index / Elements;
7260 return Mask[Index] == 0 ? 0 : 1;
7290 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7298 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7300 for (
unsigned j = 0; j < NumElts; j += 2) {
7301 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7302 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7307 if (M.size() == NumElts*2)
7322 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7325 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7327 for (
unsigned j = 0; j < NumElts; j += 2) {
7328 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7329 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7334 if (M.size() == NumElts*2)
7354 if (M.size() != NumElts && M.size() != NumElts*2)
7357 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7359 for (
unsigned j = 0; j < NumElts; ++j) {
7360 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7365 if (M.size() == NumElts*2)
7384 if (M.size() != NumElts && M.size() != NumElts*2)
7387 unsigned Half = NumElts / 2;
7388 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7390 for (
unsigned j = 0; j < NumElts; j += Half) {
7391 unsigned Idx = WhichResult;
7392 for (
unsigned k = 0; k < Half; ++k) {
7393 int MIdx = M[i + j + k];
7394 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7401 if (M.size() == NumElts*2)
7425 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7428 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7430 unsigned Idx = WhichResult * NumElts / 2;
7431 for (
unsigned j = 0; j < NumElts; j += 2) {
7432 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7433 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7439 if (M.size() == NumElts*2)
7458 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7461 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7463 unsigned Idx = WhichResult * NumElts / 2;
7464 for (
unsigned j = 0; j < NumElts; j += 2) {
7465 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7466 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7472 if (M.size() == NumElts*2)
7485 unsigned &WhichResult,
7488 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7490 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7492 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7510 if (NumElts != M.size())
7514 for (
unsigned i = 0; i != NumElts; ++i)
7515 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7524 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7532 int Ofs = Top ? 1 : 0;
7533 int Upper = SingleSource ? 0 : NumElts;
7534 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7535 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7537 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7546 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7555 unsigned Offset = Top ? 0 : 1;
7556 unsigned N = SingleSource ? 0 : NumElts;
7557 for (
unsigned i = 0; i < NumElts; i += 2) {
7558 if (M[i] >= 0 && M[i] != (
int)i)
7560 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7569 if (NumElts != M.size())
7577 unsigned Off0 = rev ? NumElts / 2 : 0;
7578 unsigned Off1 = rev ? 0 : NumElts / 2;
7579 for (
unsigned i = 0; i < NumElts; i += 2) {
7580 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7582 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7598 if (!ST->hasMVEFloatOps())
7603 if (VT != MVT::v8f16)
7624 for (
unsigned i = 1; i < 4; i++) {
7651 if (!ST->hasMVEFloatOps())
7656 if (VT != MVT::v4f32)
7672 for (
unsigned i = 1; i < 4; i++) {
7674 return Trunc.
getOpcode() == ISD::FP_EXTEND &&
7695 Val =
N->getAsZExtVal();
7697 if (ST->isThumb1Only()) {
7698 if (Val <= 255 || ~Val <= 255)
7710 EVT VT =
Op.getValueType();
7712 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7716 unsigned BitsPerBool;
7720 }
else if (NumElts == 4) {
7723 }
else if (NumElts == 8) {
7726 }
else if (NumElts == 16) {
7737 return U.get().isUndef() || U.get() == FirstOp;
7745 unsigned Bits32 = 0;
7746 for (
unsigned i = 0; i < NumElts; ++i) {
7750 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7752 Bits32 |= BoolMask << (i * BitsPerBool);
7758 for (
unsigned i = 0; i < NumElts; ++i) {
7771 if (!ST->hasMVEIntegerOps())
7775 EVT VT =
Op.getValueType();
7785 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7789 for (
unsigned I = 2;
I < NumElts;
I++) {
7805 switch (
N->getOpcode()) {
7816 return N->getOperand(1).getNode() ==
Op;
7818 switch (
N->getConstantOperandVal(0)) {
7819 case Intrinsic::arm_mve_add_predicated:
7820 case Intrinsic::arm_mve_mul_predicated:
7821 case Intrinsic::arm_mve_qadd_predicated:
7822 case Intrinsic::arm_mve_vhadd:
7823 case Intrinsic::arm_mve_hadd_predicated:
7824 case Intrinsic::arm_mve_vqdmulh:
7825 case Intrinsic::arm_mve_qdmulh_predicated:
7826 case Intrinsic::arm_mve_vqrdmulh:
7827 case Intrinsic::arm_mve_qrdmulh_predicated:
7828 case Intrinsic::arm_mve_vqdmull:
7829 case Intrinsic::arm_mve_vqdmull_predicated:
7831 case Intrinsic::arm_mve_sub_predicated:
7832 case Intrinsic::arm_mve_qsub_predicated:
7833 case Intrinsic::arm_mve_vhsub:
7834 case Intrinsic::arm_mve_hsub_predicated:
7835 return N->getOperand(2).getNode() ==
Op;
7850 EVT VT =
Op.getValueType();
7858 APInt SplatBits, SplatUndef;
7859 unsigned SplatBitSize;
7861 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7868 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7870 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7871 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7872 : SplatBitSize == 16 ? MVT::v8i16
7879 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7880 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7885 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7893 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7895 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7903 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7913 if (
ST->hasMVEIntegerOps() &&
7914 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7915 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7916 : SplatBitSize == 16 ? MVT::v8i16
7933 bool isOnlyLowElement =
true;
7934 bool usesOnlyOneValue =
true;
7935 bool hasDominantValue =
false;
7940 DenseMap<SDValue, unsigned> ValueCounts;
7942 for (
unsigned i = 0; i < NumElts; ++i) {
7947 isOnlyLowElement =
false;
7951 unsigned &
Count = ValueCounts[
V];
7954 if (++
Count > (NumElts / 2)) {
7955 hasDominantValue =
true;
7959 if (ValueCounts.
size() != 1)
7960 usesOnlyOneValue =
false;
7961 if (!
Value.getNode() && !ValueCounts.
empty())
7964 if (ValueCounts.
empty())
7976 if (hasDominantValue && EltSize <= 32) {
7985 ConstantSDNode *constIndex;
7992 if (VT !=
Value->getOperand(0).getValueType()) {
8005 if (!usesOnlyOneValue) {
8008 for (
unsigned I = 0;
I < NumElts; ++
I) {
8013 Ops.push_back(
Op.getOperand(
I));
8023 assert(FVT == MVT::f32 || FVT == MVT::f16);
8024 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
8025 for (
unsigned i = 0; i < NumElts; ++i)
8026 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, IVT,
8030 Val = LowerBUILD_VECTOR(Val, DAG, ST);
8032 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8034 if (usesOnlyOneValue) {
8061 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
8081 if (EltSize >= 32) {
8087 for (
unsigned i = 0; i < NumElts; ++i)
8088 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, EltVT,
Op.getOperand(i)));
8090 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8101 for (
unsigned i = 0 ; i < NumElts; ++i) {
8120 EVT VT =
Op.getValueType();
8123 struct ShuffleSourceInfo {
8125 unsigned MinElt = std::numeric_limits<unsigned>::max();
8126 unsigned MaxElt = 0;
8136 int WindowScale = 1;
8138 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8146 for (
unsigned i = 0; i < NumElts; ++i) {
8161 SDValue SourceVec =
V.getOperand(0);
8163 if (Source == Sources.
end())
8167 unsigned EltNo =
V.getConstantOperandVal(1);
8174 if (Sources.
size() > 2)
8180 for (
auto &Source : Sources) {
8181 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8182 if (SrcEltTy.
bitsLT(SmallestEltTy))
8183 SmallestEltTy = SrcEltTy;
8185 unsigned ResMultiplier =
8193 for (
auto &Src : Sources) {
8194 EVT SrcVT = Src.ShuffleVec.getValueType();
8198 if (SrcVTSize == VTSize)
8207 if (SrcVTSize < VTSize) {
8208 if (2 * SrcVTSize != VTSize)
8214 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8218 if (SrcVTSize != 2 * VTSize)
8221 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8226 if (Src.MinElt >= NumSrcElts) {
8231 Src.WindowBase = -NumSrcElts;
8232 }
else if (Src.MaxElt < NumSrcElts) {
8249 Src.WindowBase = -Src.MinElt;
8256 for (
auto &Src : Sources) {
8257 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8258 if (SrcEltTy == SmallestEltTy)
8263 Src.WindowBase *= Src.WindowScale;
8268 for (
auto Src : Sources)
8269 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8277 if (
Entry.isUndef())
8286 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8289 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8293 int *LaneMask = &
Mask[i * ResMultiplier];
8295 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8296 ExtractBase += NumElts * (Src - Sources.begin());
8297 for (
int j = 0;
j < LanesDefined; ++
j)
8298 LaneMask[j] = ExtractBase + j;
8304 assert(Sources.size() <= 2 &&
"Too many sources!");
8307 for (
unsigned i = 0; i < Sources.size(); ++i)
8336 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8356 unsigned PFIndexes[4];
8357 for (
unsigned i = 0; i != 4; ++i) {
8361 PFIndexes[i] = M[i];
8365 unsigned PFTableIndex =
8366 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8368 unsigned Cost = (PFEntry >> 30);
8374 bool ReverseVEXT, isV_UNDEF;
8375 unsigned Imm, WhichResult;
8378 if (EltSize >= 32 ||
8385 else if (Subtarget->hasNEON() &&
8390 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8393 else if (Subtarget->hasMVEIntegerOps() &&
8397 else if (Subtarget->hasMVEIntegerOps() &&
8411 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8412 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8413 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8416 if (LHSID == (1*9+2)*9+3)
return LHS;
8417 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8474 for (
int I : ShuffleMask)
8487 EVT VT =
Op.getValueType();
8489 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8490 "Expect an v8i16/v16i8 type");
8496 std::vector<int> NewMask;
8500 NewMask.push_back(i);
8540 if (VT != MVT::v16i1)
8551 return DAG.
getNode(ISD::BITCAST, dl, NewVT, PredAsVector);
8556 EVT VT =
Op.getValueType();
8560 assert(ST->hasMVEIntegerOps() &&
8561 "No support for vector shuffle of boolean predicates");
8587 "Expected identical vector type in expanded i1 shuffle!");
8591 PredAsVector2, ShuffleMask);
8596 if (VT == MVT::v2i1) {
8613 EVT VT =
Op.getValueType();
8617 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8618 "Unexpected vector type");
8620 int QuarterSize = NumElts / 4;
8629 for (
int i = 0; i <
Length; i++) {
8630 if (ShuffleMask[Start + i] >= 0) {
8631 if (ShuffleMask[Start + i] %
Length != i)
8633 MovIdx = ShuffleMask[Start + i] /
Length;
8641 for (
int i = 1; i <
Length; i++) {
8642 if (ShuffleMask[Start + i] >= 0 &&
8643 (ShuffleMask[Start + i] /
Length != MovIdx ||
8644 ShuffleMask[Start + i] %
Length != i))
8650 for (
int Part = 0; Part < 4; ++Part) {
8652 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8666 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8671 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8673 for (
int Part = 0; Part < 4; ++Part)
8674 for (
int i = 0; i < QuarterSize; i++)
8676 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8678 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8681 for (
int Part = 0; Part < 4; ++Part)
8697 EVT VT =
Op.getValueType();
8709 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8713 if (Mask[i] != i + BaseOffset) {
8714 if (OffElement == -1)
8720 return NonUndef > 2 && OffElement != -1;
8724 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8726 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8737 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8748 EVT VT =
Op.getValueType();
8752 if (ST->hasMVEIntegerOps() && EltSize == 1)
8763 if (EltSize <= 32) {
8767 if (Lane == -1) Lane = 0;
8778 bool IsScalarToVector =
true;
8781 IsScalarToVector =
false;
8784 if (IsScalarToVector)
8791 bool ReverseVEXT =
false;
8793 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8817 unsigned WhichResult = 0;
8818 bool isV_UNDEF =
false;
8819 if (ST->hasNEON()) {
8821 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8828 if (ST->hasMVEIntegerOps()) {
8863 }) &&
"Unexpected shuffle index into UNDEF operand!");
8866 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8869 assert((WhichResult == 0) &&
8870 "In-place shuffle of concat can only have one result!");
8879 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8883 for (
bool Top : {
false,
true}) {
8884 for (
bool SingleSource : {
false,
true}) {
8885 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8890 SingleSource ? V1 : V2);
8906 unsigned PFIndexes[4];
8907 for (
unsigned i = 0; i != 4; ++i) {
8908 if (ShuffleMask[i] < 0)
8911 PFIndexes[i] = ShuffleMask[i];
8915 unsigned PFTableIndex =
8916 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8918 unsigned Cost = (PFEntry >> 30);
8924 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8925 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8935 if (EltSize >= 32) {
8940 V1 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V1);
8941 V2 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V2);
8943 for (
unsigned i = 0; i < NumElts; ++i) {
8944 if (ShuffleMask[i] < 0)
8948 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8953 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8956 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8960 if (ST->hasNEON() && VT == MVT::v8i8)
8964 if (ST->hasMVEIntegerOps())
8973 EVT VecVT =
Op.getOperand(0).getValueType();
8976 assert(ST->hasMVEIntegerOps() &&
8977 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8981 unsigned Lane =
Op.getConstantOperandVal(2);
8982 unsigned LaneWidth =
8984 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
9002 if (Subtarget->hasMVEIntegerOps() &&
9003 Op.getValueType().getScalarSizeInBits() == 1)
9027 IVecIn, IElt, Lane);
9028 return DAG.
getNode(ISD::BITCAST, dl, VecVT, IVecOut);
9036 EVT VecVT =
Op.getOperand(0).getValueType();
9039 assert(ST->hasMVEIntegerOps() &&
9040 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9044 unsigned Lane =
Op.getConstantOperandVal(1);
9045 unsigned LaneWidth =
9076 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
9077 "Unexpected custom CONCAT_VECTORS lowering");
9079 "Unexpected custom CONCAT_VECTORS lowering");
9080 assert(ST->hasMVEIntegerOps() &&
9081 "CONCAT_VECTORS lowering only supported for MVE");
9085 EVT Op2VT = V2.getValueType();
9086 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9087 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9088 "Unexpected i1 concat operations!");
9101 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9115 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9116 EVT NewVT = NewV.getValueType();
9117 EVT ConcatVT = ConVec.getValueType();
9118 unsigned ExtScale = 1;
9119 if (NewVT == MVT::v2f64) {
9133 ConVec = ExtractInto(NewV1, ConVec, j);
9134 ConVec = ExtractInto(NewV2, ConVec, j);
9144 while (ConcatOps.
size() > 1) {
9145 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
9148 ConcatOps[
I / 2] = ConcatPair(V1, V2);
9152 return ConcatOps[0];
9157 EVT VT =
Op->getValueType(0);
9163 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9164 "unexpected CONCAT_VECTORS");
9171 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op0),
9175 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op1),
9177 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Val);
9185 EVT VT =
Op.getValueType();
9191 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9192 assert(ST->hasMVEIntegerOps() &&
9193 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9203 EVT SubVT = MVT::v4i32;
9205 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9220 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9236 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9237 EVT VT =
N->getValueType(0);
9238 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9239 "Expected a vector i1 type!");
9241 EVT FromVT =
Op.getValueType();
9252 if (!Subtarget->hasMVEIntegerOps())
9255 EVT ToVT =
N->getValueType(0);
9298 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9300 EVT FromVT =
N->getOperand(0).getValueType();
9301 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9312 if (!Subtarget->hasMVEIntegerOps())
9317 EVT ToVT =
N->getValueType(0);
9318 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9321 EVT FromVT =
Op.getValueType();
9322 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9333 SDValue Ext1 = Ext.getValue(1);
9336 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9337 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9349 EVT VT =
N->getValueType(0);
9350 if (VT == MVT::v2i64 &&
N->getOpcode() == ISD::BITCAST) {
9351 SDNode *BVN =
N->getOperand(0).getNode();
9356 unsigned HiElt = 1 - LoElt;
9361 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9377 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9378 SDNode *Elt =
N->getOperand(i).getNode();
9381 unsigned HalfSize = EltSize / 2;
9383 if (!
isIntN(HalfSize,
C->getSExtValue()))
9386 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9425 switch (OrigSimpleTy) {
9441 unsigned ExtOpcode) {
9464 if (ExtendedTy == LD->getMemoryVT())
9465 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9466 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9467 LD->getMemOperand()->getFlags());
9473 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9474 LD->getMemoryVT(), LD->getAlign(),
9475 LD->getMemOperand()->getFlags());
9488 N->getOperand(0)->getValueType(0),
9494 "Expected extending load");
9500 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9508 if (
N->getOpcode() == ISD::BITCAST) {
9509 SDNode *BVN =
N->getOperand(0).getNode();
9511 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9519 EVT VT =
N->getValueType(0);
9525 for (
unsigned i = 0; i != NumElts; ++i) {
9526 const APInt &CInt =
N->getConstantOperandAPInt(i);
9535 unsigned Opcode =
N->getOpcode();
9537 SDNode *N0 =
N->getOperand(0).getNode();
9538 SDNode *N1 =
N->getOperand(1).getNode();
9546 unsigned Opcode =
N->getOpcode();
9548 SDNode *N0 =
N->getOperand(0).getNode();
9549 SDNode *N1 =
N->getOperand(1).getNode();
9559 EVT VT =
Op.getValueType();
9561 "unexpected type for custom-lowering ISD::MUL");
9562 SDNode *N0 =
Op.getOperand(0).getNode();
9563 SDNode *N1 =
Op.getOperand(1).getNode();
9564 unsigned NewOpc = 0;
9568 if (isN0SExt && isN1SExt)
9573 if (isN0ZExt && isN1ZExt)
9575 else if (isN1SExt || isN1ZExt) {
9592 if (VT == MVT::v2i64)
9609 "unexpected types for extended operands to VMULL");
9610 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9626 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N00), Op1),
9628 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N01), Op1));
9645 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9652 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32,
X);
9655 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32,
X);
9679 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9682 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9690 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9693 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9703 EVT VT =
Op.getValueType();
9704 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9705 "unexpected type for custom-lowering ISD::SDIV");
9712 if (VT == MVT::v8i8) {
9740 EVT VT =
Op.getValueType();
9741 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9742 "unexpected type for custom-lowering ISD::UDIV");
9749 if (VT == MVT::v8i8) {
9788 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9791 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9795 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9803 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9806 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9816 EVT VT =
N->getValueType(0);
9830 Op.getOperand(1), Carry);
9844 Op.getOperand(1), Carry);
9861 EVT VT =
Op.getValueType();
9862 assert((VT == MVT::i32 || VT == MVT::i64) &&
9863 "unexpected type for custom lowering DIV");
9869 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9871 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9878 for (
auto AI : {1, 0}) {
9880 Args.emplace_back(Operand,
9888 ES, std::move(Args));
9898ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9906 const bool MinSize =
ST.hasMinSize();
9907 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9908 :
ST.hasDivideInARMMode();
9912 if (
N->getOperand(0).getValueType().isVector())
9917 if (!(MinSize && HasDivide))
9930 if (Divisor.
sgt(128))
9938 assert(
Op.getValueType() == MVT::i32 &&
9939 "unexpected type for custom lowering DIV");
9945 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9951 if (
N->getValueType(0) == MVT::i32)
9959void ARMTargetLowering::ExpandDIV_Windows(
9964 assert(
Op.getValueType() == MVT::i64 &&
9965 "unexpected type for custom lowering DIV");
9982 EVT MemVT = LD->getMemoryVT();
9983 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9984 MemVT == MVT::v16i1) &&
9985 "Expected a predicate type!");
9986 assert(MemVT ==
Op.getValueType());
9988 "Expected a non-extending load");
9989 assert(LD->isUnindexed() &&
"Expected a unindexed load");
10003 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
10005 LD->getMemOperand());
10012 if (MemVT != MVT::v16i1)
10021 EVT MemVT =
LD->getMemoryVT();
10022 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10024 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10025 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
10026 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10030 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10040 EVT MemVT = ST->getMemoryVT();
10041 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10042 MemVT == MVT::v16i1) &&
10043 "Expected a predicate type!");
10044 assert(MemVT == ST->getValue().getValueType());
10045 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10046 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10051 SDValue Build = ST->getValue();
10052 if (MemVT != MVT::v16i1) {
10071 ST->getChain(), dl, GRP, ST->getBasePtr(),
10073 ST->getMemOperand());
10079 EVT MemVT = ST->getMemoryVT();
10080 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10082 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10098 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10099 MemVT, ST->getMemOperand());
10100 }
else if (Subtarget->hasMVEIntegerOps() &&
10101 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10102 MemVT == MVT::v16i1))) {
10117 MVT VT =
Op.getSimpleValueType();
10119 SDValue PassThru =
N->getPassThru();
10130 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10131 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10132 N->getExtensionType(),
N->isExpandingLoad());
10134 bool PassThruIsCastZero = (PassThru.
getOpcode() == ISD::BITCAST ||
10137 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10144 if (!ST->hasMVEIntegerOps())
10148 unsigned BaseOpcode = 0;
10149 switch (
Op->getOpcode()) {
10151 case ISD::VECREDUCE_FADD: BaseOpcode =
ISD::FADD;
break;
10152 case ISD::VECREDUCE_FMUL: BaseOpcode =
ISD::FMUL;
break;
10153 case ISD::VECREDUCE_MUL: BaseOpcode =
ISD::MUL;
break;
10154 case ISD::VECREDUCE_AND: BaseOpcode =
ISD::AND;
break;
10155 case ISD::VECREDUCE_OR: BaseOpcode =
ISD::OR;
break;
10156 case ISD::VECREDUCE_XOR: BaseOpcode =
ISD::XOR;
break;
10157 case ISD::VECREDUCE_FMAX: BaseOpcode = ISD::FMAXNUM;
break;
10158 case ISD::VECREDUCE_FMIN: BaseOpcode = ISD::FMINNUM;
break;
10165 unsigned NumActiveLanes = NumElts;
10167 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10168 NumActiveLanes == 2) &&
10169 "Only expected a power 2 vector size");
10173 while (NumActiveLanes > 4) {
10176 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10177 NumActiveLanes /= 2;
10181 if (NumActiveLanes == 4) {
10191 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10192 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10193 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10199 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10203 if (EltVT !=
Op->getValueType(0))
10210 if (!ST->hasMVEFloatOps())
10217 if (!ST->hasNEON())
10225 unsigned PairwiseIntrinsic = 0;
10226 switch (
Op->getOpcode()) {
10229 case ISD::VECREDUCE_UMIN:
10230 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10232 case ISD::VECREDUCE_UMAX:
10233 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10235 case ISD::VECREDUCE_SMIN:
10236 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10238 case ISD::VECREDUCE_SMAX:
10239 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10245 unsigned NumActiveLanes = NumElts;
10247 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10248 NumActiveLanes == 2) &&
10249 "Only expected a power 2 vector size");
10255 VT =
Lo.getValueType();
10257 NumActiveLanes /= 2;
10261 while (NumActiveLanes > 1) {
10263 NumActiveLanes /= 2;
10270 if (EltVT !=
Op.getValueType()) {
10271 unsigned Extend = 0;
10272 switch (
Op->getOpcode()) {
10275 case ISD::VECREDUCE_UMIN:
10276 case ISD::VECREDUCE_UMAX:
10279 case ISD::VECREDUCE_SMIN:
10280 case ISD::VECREDUCE_SMAX:
10284 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10329 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10335 SDLoc dl(V.getNode());
10336 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10346 assert(
N->getValueType(0) == MVT::i64 &&
10347 "AtomicCmpSwap on types less than 64 should be legal");
10356 ARM::CMP_SWAP_64,
SDLoc(
N),
10357 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10376 EVT VT =
Op.getValueType();
10385 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10387 Chain, IsSignaling);
10388 if (!
RHS.getNode()) {
10404 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10406 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10407 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10424 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10427 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10440 if (!IsSigned && Subtarget->isThumb1Only()) {
10458 Sub1Result, Sub1Result, Flags1);
10473 if (
Op.getValueType() != MVT::i32)
10496 bool CanUseAdd =
false;
10537 GTCondValue, Flags);
10542 LTCondValue, Flags);
10544 if (
Op.getValueType() != MVT::i32)
10552 switch (
Op.getOpcode()) {
10561 case ISD::BRCOND:
return LowerBRCOND(
Op, DAG);
10562 case ISD::BR_CC:
return LowerBR_CC(
Op, DAG);
10563 case ISD::BR_JT:
return LowerBR_JT(
Op, DAG);
10584 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10588 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10589 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10609 case ISD::SET_ROUNDING:
return LowerSET_ROUNDING(
Op, DAG);
10610 case ISD::SET_FPMODE:
10611 return LowerSET_FPMODE(
Op, DAG);
10612 case ISD::RESET_FPMODE:
10613 return LowerRESET_FPMODE(
Op, DAG);
10616 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10617 return LowerDIV_Windows(
Op, DAG,
true);
10620 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10621 return LowerDIV_Windows(
Op, DAG,
false);
10628 return LowerSignedALUO(
Op, DAG);
10631 return LowerUnsignedALUO(
Op, DAG);
10643 case ISD::VECREDUCE_MUL:
10644 case ISD::VECREDUCE_AND:
10645 case ISD::VECREDUCE_OR:
10646 case ISD::VECREDUCE_XOR:
10648 case ISD::VECREDUCE_FADD:
10649 case ISD::VECREDUCE_FMUL:
10650 case ISD::VECREDUCE_FMIN:
10651 case ISD::VECREDUCE_FMAX:
10653 case ISD::VECREDUCE_UMIN:
10654 case ISD::VECREDUCE_UMAX:
10655 case ISD::VECREDUCE_SMIN:
10656 case ISD::VECREDUCE_SMAX:
10658 case ISD::ATOMIC_LOAD:
10659 case ISD::ATOMIC_STORE:
10663 case ISD::DYNAMIC_STACKALLOC:
10664 if (Subtarget->isTargetWindows())
10665 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10670 case ISD::FP_EXTEND:
return LowerFP_EXTEND(
Op, DAG);
10674 return LowerSPONENTRY(
Op, DAG);
10675 case ISD::FP_TO_BF16:
10676 return LowerFP_TO_BF16(
Op, DAG);
10680 return LowerCMP(
Op, DAG);
10682 return LowerABS(
Op, DAG);
10687 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10688 Op.getOperand(1).getValueType() == MVT::bf16) &&
10689 "Expected custom lowering of rounding operations only for f16");
10692 {
Op.getOperand(0),
Op.getOperand(1)});
10693 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10694 {Ext.getValue(1), Ext.getValue(0)});
10701 unsigned IntNo =
N->getConstantOperandVal(0);
10703 if (IntNo == Intrinsic::arm_smlald)
10705 else if (IntNo == Intrinsic::arm_smlaldx)
10707 else if (IntNo == Intrinsic::arm_smlsld)
10709 else if (IntNo == Intrinsic::arm_smlsldx)
10716 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10720 N->getOperand(1),
N->getOperand(2),
10732 switch (
N->getOpcode()) {
10739 Res = ExpandBITCAST(
N, DAG, Subtarget);
10748 Res = LowerREM(
N, DAG);
10752 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10763 case ISD::READCYCLECOUNTER:
10768 assert(Subtarget->isTargetWindows() &&
"can only expand DIV on Windows");
10771 case ISD::ATOMIC_CMP_SWAP:
10806 "ROPI/RWPI not currently supported with SjLj");
10815 bool isThumb = Subtarget->isThumb();
10816 bool isThumb2 = Subtarget->
isThumb2();
10819 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10825 : &ARM::GPRRegClass;
10843 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10849 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10855 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10873 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10878 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10883 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10888 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10894 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10909 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10915 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10931 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10938 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10939 : &ARM::GPRnopcRegClass;
10943 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10944 unsigned MaxCSNum = 0;
10945 for (MachineBasicBlock &BB : *MF) {
10951 for (MachineInstr &
II : BB) {
10952 if (!
II.isEHLabel())
10955 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10956 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10958 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10959 for (
unsigned Idx : CallSiteIdxs) {
10960 CallSiteNumToLPad[Idx].push_back(&BB);
10961 MaxCSNum = std::max(MaxCSNum, Idx);
10968 std::vector<MachineBasicBlock*> LPadList;
10969 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10970 LPadList.reserve(CallSiteNumToLPad.
size());
10971 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10972 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10973 for (MachineBasicBlock *
MBB : MBBList) {
10974 LPadList.push_back(
MBB);
10979 assert(!LPadList.empty() &&
10980 "No landing pad destinations for the dispatch jump table!");
10983 MachineJumpTableInfo *JTI =
10990 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10993 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10995 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10998 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
11002 MF->insert(MF->end(), DispatchBB);
11003 MF->insert(MF->end(), DispContBB);
11004 MF->insert(MF->end(), TrapBB);
11008 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11010 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
11014 MachineInstrBuilder MIB;
11015 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11017 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
11027 unsigned NumLPads = LPadList.size();
11028 if (Subtarget->isThumb2()) {
11029 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11030 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11036 if (NumLPads < 256) {
11037 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11039 .
addImm(LPadList.size())
11042 Register VReg1 =
MRI->createVirtualRegister(TRC);
11043 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11044 .
addImm(NumLPads & 0xFFFF)
11047 unsigned VReg2 = VReg1;
11048 if ((NumLPads & 0xFFFF0000) != 0) {
11049 VReg2 =
MRI->createVirtualRegister(TRC);
11050 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11056 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11062 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11067 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11068 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11072 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11073 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11080 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11084 }
else if (Subtarget->isThumb()) {
11085 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11086 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11092 if (NumLPads < 256) {
11093 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11098 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11103 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11104 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11106 Register VReg1 =
MRI->createVirtualRegister(TRC);
11107 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11111 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11117 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11122 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
11123 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11129 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11130 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11134 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11135 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11141 MachineMemOperand *JTMMOLd =
11145 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11146 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11152 unsigned NewVReg6 = NewVReg5;
11153 if (IsPositionIndependent) {
11154 NewVReg6 =
MRI->createVirtualRegister(TRC);
11155 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11162 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11166 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11167 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11173 if (NumLPads < 256) {
11174 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11178 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11179 Register VReg1 =
MRI->createVirtualRegister(TRC);
11180 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11181 .
addImm(NumLPads & 0xFFFF)
11184 unsigned VReg2 = VReg1;
11185 if ((NumLPads & 0xFFFF0000) != 0) {
11186 VReg2 =
MRI->createVirtualRegister(TRC);
11187 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11193 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11198 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11203 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11204 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11206 Register VReg1 =
MRI->createVirtualRegister(TRC);
11207 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11212 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11223 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11224 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11229 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11230 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11234 MachineMemOperand *JTMMOLd =
11237 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11238 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11245 if (IsPositionIndependent) {
11246 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11251 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11258 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11259 for (MachineBasicBlock *CurMBB : LPadList) {
11260 if (SeenMBBs.
insert(CurMBB).second)
11267 for (MachineBasicBlock *BB : InvokeBBs) {
11271 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11272 while (!Successors.empty()) {
11273 MachineBasicBlock *SMBB = Successors.pop_back_val();
11275 BB->removeSuccessor(SMBB);
11281 BB->normalizeSuccProbs();
11288 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11289 if (!
II->isCall())
continue;
11291 DenseSet<unsigned> DefRegs;
11293 OI =
II->operands_begin(), OE =
II->operands_end();
11295 if (!OI->isReg())
continue;
11296 DefRegs.
insert(OI->getReg());
11299 MachineInstrBuilder MIB(*MF, &*
II);
11301 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11302 unsigned Reg = SavedRegs[i];
11303 if (Subtarget->isThumb2() &&
11304 !ARM::tGPRRegClass.contains(
Reg) &&
11305 !ARM::hGPRRegClass.contains(
Reg))
11307 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11309 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11321 for (MachineBasicBlock *MBBLPad : MBBLPads)
11322 MBBLPad->setIsEHPad(
false);
11325 MI.eraseFromParent();
11338static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11340 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11341 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11343 return LdSize == 4 ? ARM::tLDRi
11344 : LdSize == 2 ? ARM::tLDRHi
11345 : LdSize == 1 ? ARM::tLDRBi : 0;
11347 return LdSize == 4 ? ARM::t2LDR_POST
11348 : LdSize == 2 ? ARM::t2LDRH_POST
11349 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11350 return LdSize == 4 ? ARM::LDR_POST_IMM
11351 : LdSize == 2 ? ARM::LDRH_POST
11352 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11357static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11359 return StSize == 16 ? ARM::VST1q32wb_fixed
11360 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11362 return StSize == 4 ? ARM::tSTRi
11363 : StSize == 2 ? ARM::tSTRHi
11364 : StSize == 1 ? ARM::tSTRBi : 0;
11366 return StSize == 4 ? ARM::t2STR_POST
11367 : StSize == 2 ? ARM::t2STRH_POST
11368 : StSize == 1 ? ARM::t2STRB_POST : 0;
11369 return StSize == 4 ? ARM::STR_POST_IMM
11370 : StSize == 2 ? ARM::STRH_POST
11371 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11378 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11379 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11380 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11381 assert(LdOpc != 0 &&
"Should have a load opcode");
11388 }
else if (IsThumb1) {
11394 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11399 }
else if (IsThumb2) {
11419 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11420 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11421 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11422 assert(StOpc != 0 &&
"Should have a store opcode");
11424 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11429 }
else if (IsThumb1) {
11436 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11441 }
else if (IsThumb2) {
11442 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11448 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11463 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11469 unsigned SizeVal =
MI.getOperand(2).getImm();
11470 unsigned Alignment =
MI.getOperand(3).getImm();
11475 unsigned UnitSize = 0;
11476 const TargetRegisterClass *TRC =
nullptr;
11477 const TargetRegisterClass *VecTRC =
nullptr;
11479 bool IsThumb1 = Subtarget->isThumb1Only();
11480 bool IsThumb2 = Subtarget->isThumb2();
11481 bool IsThumb = Subtarget->isThumb();
11483 if (Alignment & 1) {
11485 }
else if (Alignment & 2) {
11490 Subtarget->hasNEON()) {
11491 if ((Alignment % 16 == 0) && SizeVal >= 16)
11493 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11502 bool IsNeon = UnitSize >= 8;
11503 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11505 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11506 : UnitSize == 8 ? &ARM::DPRRegClass
11509 unsigned BytesLeft = SizeVal % UnitSize;
11510 unsigned LoopSize = SizeVal - BytesLeft;
11512 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11516 unsigned srcIn = src;
11517 unsigned destIn = dest;
11518 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11519 Register srcOut =
MRI.createVirtualRegister(TRC);
11520 Register destOut =
MRI.createVirtualRegister(TRC);
11521 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11523 IsThumb1, IsThumb2);
11525 IsThumb1, IsThumb2);
11533 for (
unsigned i = 0; i < BytesLeft; i++) {
11534 Register srcOut =
MRI.createVirtualRegister(TRC);
11535 Register destOut =
MRI.createVirtualRegister(TRC);
11536 Register scratch =
MRI.createVirtualRegister(TRC);
11538 IsThumb1, IsThumb2);
11540 IsThumb1, IsThumb2);
11544 MI.eraseFromParent();
11570 MF->
insert(It, loopMBB);
11571 MF->
insert(It, exitMBB);
11574 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11584 Register varEnd =
MRI.createVirtualRegister(TRC);
11585 if (Subtarget->useMovt()) {
11586 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11589 }
else if (Subtarget->genExecuteOnly()) {
11590 assert(IsThumb &&
"Non-thumb expected to have used movt");
11599 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11600 MachineMemOperand *CPMMO =
11624 MachineBasicBlock *entryBB = BB;
11626 Register varLoop =
MRI.createVirtualRegister(TRC);
11627 Register varPhi =
MRI.createVirtualRegister(TRC);
11628 Register srcLoop =
MRI.createVirtualRegister(TRC);
11629 Register srcPhi =
MRI.createVirtualRegister(TRC);
11630 Register destLoop =
MRI.createVirtualRegister(TRC);
11631 Register destPhi =
MRI.createVirtualRegister(TRC);
11639 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11645 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11647 IsThumb1, IsThumb2);
11649 IsThumb1, IsThumb2);
11653 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11659 MachineInstrBuilder MIB =
11661 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11670 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11679 auto StartOfExit = exitMBB->
begin();
11683 unsigned srcIn = srcLoop;
11684 unsigned destIn = destLoop;
11685 for (
unsigned i = 0; i < BytesLeft; i++) {
11686 Register srcOut =
MRI.createVirtualRegister(TRC);
11687 Register destOut =
MRI.createVirtualRegister(TRC);
11688 Register scratch =
MRI.createVirtualRegister(TRC);
11689 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11690 IsThumb1, IsThumb2);
11691 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11692 IsThumb1, IsThumb2);
11697 MI.eraseFromParent();
11705 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11708 assert(Subtarget->isTargetWindows() &&
11709 "__chkstk is only supported on Windows");
11710 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11730 switch (TM.getCodeModel()) {
11772 MI.eraseFromParent();
11781 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11796 .
addReg(
MI.getOperand(0).getReg())
11804 MI.eraseFromParent();
11828 if (miI == BB->
end()) {
11830 if (Succ->isLiveIn(ARM::CPSR))
11836 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11848 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11849 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11855 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11856 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11862 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11863 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11866 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11867 .
addUse(TotalIterationsReg)
11874 return TotalIterationsReg;
11885 Register TotalIterationsReg,
bool IsMemcpy) {
11892 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11893 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11894 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11902 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11903 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11904 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11911 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11912 Register RemainingLoopIterationsReg =
11913 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11914 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11915 .
addUse(TotalIterationsReg)
11917 .
addUse(RemainingLoopIterationsReg)
11921 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11922 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11923 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11924 .
addUse(ElementCountReg)
11926 .
addUse(RemainingElementsReg)
11930 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11931 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11932 .
addUse(PredCounterPhiReg)
11937 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11938 .
addUse(PredCounterPhiReg)
11946 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11947 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11956 SrcValueReg = OpSrcReg;
11958 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11969 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11970 .
addUse(LoopCounterPhiReg)
11973 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11974 .
addUse(RemainingLoopIterationsReg)
11992 "Invalid call instruction for a KCFI check");
11995 switch (
MBBI->getOpcode()) {
11998 case ARM::BLX_pred:
11999 case ARM::BLX_noip:
12000 case ARM::BLX_pred_noip:
12002 TargetOp = &
MBBI->getOperand(0);
12004 case ARM::TCRETURNri:
12005 case ARM::TCRETURNrinotr12:
12006 case ARM::TAILJMPr:
12007 case ARM::TAILJMPr4:
12008 TargetOp = &
MBBI->getOperand(0);
12014 case ARM::tBLXr_noip:
12015 case ARM::tBX_CALL:
12016 TargetOp = &
MBBI->getOperand(2);
12019 case ARM::tTAILJMPr:
12020 TargetOp = &
MBBI->getOperand(0);
12026 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
12030 unsigned KCFICheckOpcode;
12031 if (Subtarget->isThumb()) {
12032 if (Subtarget->isThumb2()) {
12033 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
12035 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
12038 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
12052 bool isThumb2 = Subtarget->isThumb2();
12053 switch (
MI.getOpcode()) {
12060 case ARM::tLDR_postidx: {
12064 .
add(
MI.getOperand(2))
12065 .
add(
MI.getOperand(3))
12066 .
add(
MI.getOperand(4))
12067 .
add(
MI.getOperand(0))
12069 MI.eraseFromParent();
12073 case ARM::MVE_MEMCPYLOOPINST:
12074 case ARM::MVE_MEMSETLOOPINST: {
12104 Register OpDestReg =
MI.getOperand(0).getReg();
12105 Register OpSrcReg =
MI.getOperand(1).getReg();
12106 Register OpSizeReg =
MI.getOperand(2).getReg();
12126 if (TpExit == BB) {
12128 "block containing memcpy/memset Pseudo");
12141 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12143 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12146 Properties.resetNoPHIs();
12158 MI.eraseFromParent();
12168 case ARM::t2STR_preidx:
12169 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12171 case ARM::t2STRB_preidx:
12172 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12174 case ARM::t2STRH_preidx:
12175 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12178 case ARM::STRi_preidx:
12179 case ARM::STRBi_preidx: {
12180 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12181 : ARM::STRB_PRE_IMM;
12183 unsigned Offset =
MI.getOperand(4).getImm();
12191 .
add(
MI.getOperand(0))
12192 .
add(
MI.getOperand(1))
12193 .
add(
MI.getOperand(2))
12195 .
add(
MI.getOperand(5))
12196 .
add(
MI.getOperand(6))
12198 MI.eraseFromParent();
12201 case ARM::STRr_preidx:
12202 case ARM::STRBr_preidx:
12203 case ARM::STRH_preidx: {
12205 switch (
MI.getOpcode()) {
12207 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12208 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12209 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12214 MI.eraseFromParent();
12218 case ARM::tMOVCCr_pseudo: {
12236 F->insert(It, copy0MBB);
12237 F->insert(It, sinkMBB);
12240 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12246 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12262 .
addImm(
MI.getOperand(3).getImm())
12263 .
addReg(
MI.getOperand(4).getReg());
12278 .
addReg(
MI.getOperand(1).getReg())
12280 .
addReg(
MI.getOperand(2).getReg())
12283 MI.eraseFromParent();
12288 case ARM::BCCZi64: {
12294 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12299 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12303 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12309 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12313 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12323 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12332 MI.eraseFromParent();
12336 case ARM::Int_eh_sjlj_setjmp:
12337 case ARM::Int_eh_sjlj_setjmp_nofp:
12338 case ARM::tInt_eh_sjlj_setjmp:
12339 case ARM::t2Int_eh_sjlj_setjmp:
12340 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12343 case ARM::Int_eh_sjlj_setup_dispatch:
12344 EmitSjLjDispatchBlock(
MI, BB);
12346 case ARM::COPY_STRUCT_BYVAL_I32:
12348 return EmitStructByval(
MI, BB);
12349 case ARM::WIN__CHKSTK:
12350 return EmitLowered__chkstk(
MI, BB);
12351 case ARM::WIN__DBZCHK:
12352 return EmitLowered__dbzchk(
MI, BB);
12368 if (!
Node->hasAnyUseOfValue(0)) {
12369 MI.getOperand(0).setIsDead(
true);
12371 if (!
Node->hasAnyUseOfValue(1)) {
12372 MI.getOperand(1).setIsDead(
true);
12376 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12377 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12378 : &ARM::GPRRegClass);
12385 if (
MI.getOpcode() == ARM::MEMCPY) {
12406 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12407 &&
"converted opcode should be the same except for cc_out"
12408 " (and, on Thumb1, pred)");
12416 if (Subtarget->isThumb1Only()) {
12417 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12418 MI.addOperand(
MI.getOperand(1));
12419 MI.removeOperand(1);
12423 for (
unsigned i =
MI.getNumOperands(); i--;) {
12425 if (
op.isReg() &&
op.isUse()) {
12428 MI.tieOperands(DefIdx, i);
12436 ccOutIdx =
MCID->getNumOperands() - 1;
12438 ccOutIdx =
MCID->getNumOperands() - 1;
12442 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12443 assert(!NewOpc &&
"Optional cc_out operand required");
12448 bool definesCPSR =
false;
12449 bool deadCPSR =
false;
12450 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12454 definesCPSR =
true;
12457 MI.removeOperand(i);
12461 if (!definesCPSR) {
12462 assert(!NewOpc &&
"Optional cc_out operand required");
12465 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12467 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12468 "expect uninitialized optional cc_out operand");
12470 if (!Subtarget->isThumb1Only())
12506 switch (
N->getOpcode()) {
12507 default:
return false;
12509 CC =
N->getOperand(0);
12531 EVT VT =
N->getValueType(0);
12532 CC =
N->getOperand(0);
12579 EVT VT =
N->getValueType(0);
12582 bool SwapSelectOps;
12584 NonConstantVal, DAG))
12590 OtherOp, NonConstantVal);
12596 CCOp, TrueVal, FalseVal);
12620 if (
N->getOpcode() ==
ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12635 if (!
N->getValueType(0).is64BitVector())
12643 EVT VT =
N->getValueType(0);
12682 EVT VT =
N->getValueType(0);
12688 Opcode = Intrinsic::arm_neon_vpaddls;
12690 Opcode = Intrinsic::arm_neon_vpaddlu;
12718 EVT VT =
N->getValueType(0);
12733 unsigned nextIndex = 0;
12784 Ops.push_back(Vec);
12801 return DAG.
getNode(ExtOp, dl, VT, tmp);
12832 if (SRA.getOpcode() !=
ISD::SRA) {
12839 if (Const->getZExtValue() != 31)
12844 if (SRA.getOperand(0) !=
Mul)
12848 SDLoc dl(AddcNode);
12849 unsigned Opcode = 0;
12855 Op0 =
Mul.getOperand(0);
12856 Op1 =
Mul.getOperand(1);
12859 Op0 =
Mul.getOperand(0);
12860 Op1 =
Mul.getOperand(1).getOperand(0);
12863 Op0 =
Mul.getOperand(0).getOperand(0);
12864 Op1 =
Mul.getOperand(1);
12867 Op0 =
Mul->getOperand(0).getOperand(0);
12868 Op1 =
Mul->getOperand(1).getOperand(0);
12877 SDValue HiMLALResult(SMLAL.getNode(), 1);
12878 SDValue LoMLALResult(SMLAL.getNode(), 0);
12884 SDValue resNode(AddcNode, 0);
12913 "Expect an ADDE or SUBE");
12917 "ADDE node has the wrong inputs");
12936 "Expect ADDC with two result values. First: i32");
12956 bool IsLeftOperandMUL =
false;
12961 IsLeftOperandMUL =
true;
12972 SDValue *LowAddSub =
nullptr;
12975 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12978 if (IsLeftOperandMUL)
12979 HiAddSub = &AddeSubeOp1;
12981 HiAddSub = &AddeSubeOp0;
12986 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12987 LoMul = &AddcSubcOp0;
12988 LowAddSub = &AddcSubcOp1;
12990 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12991 LoMul = &AddcSubcOp1;
12992 LowAddSub = &AddcSubcOp0;
13000 if (AddcSubcNode == HiAddSub->getNode() ||
13016 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13021 Ops.push_back(*HiAddSub);
13030 return SDValue(AddeSubeNode, 0);
13037 Ops.push_back(*LowAddSub);
13038 Ops.push_back(*HiAddSub);
13051 return SDValue(AddeSubeNode, 0);
13063 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13072 SDNode *UmlalNode =
nullptr;
13111 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13116 SDNode* AddcNode =
N->getOperand(2).getNode();
13117 SDNode* AddeNode =
N->getOperand(3).getNode();
13125 {N->getOperand(0), N->getOperand(1),
13126 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13150 int32_t imm =
C->getSExtValue();
13151 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13156 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13171 int64_t imm =
C->getSExtValue();
13182 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13183 N->getOperand(0),
RHS,
N->getOperand(2));
13195 if (!Subtarget->hasMVEIntegerOps())
13208 SetCC =
N->getOperand(0);
13212 TrueVal =
N->getOperand(1);
13213 FalseVal =
N->getOperand(2);
13215 LHS =
N->getOperand(0);
13216 RHS =
N->getOperand(1);
13218 TrueVal =
N->getOperand(2);
13219 FalseVal =
N->getOperand(3);
13224 unsigned int Opcode = 0;
13225 if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMIN ||
13226 FalseVal->getOpcode() == ISD::VECREDUCE_UMIN) &&
13231 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMIN ||
13232 FalseVal->getOpcode() == ISD::VECREDUCE_SMIN) &&
13237 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMAX ||
13238 FalseVal->getOpcode() == ISD::VECREDUCE_UMAX) &&
13243 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMAX ||
13244 FalseVal->getOpcode() == ISD::VECREDUCE_SMAX) &&
13253 switch (TrueVal->getOpcode()) {
13254 case ISD::VECREDUCE_UMIN:
13255 case ISD::VECREDUCE_SMIN:
13256 case ISD::VECREDUCE_UMAX:
13257 case ISD::VECREDUCE_SMAX:
13272 if (TrueVal !=
LHS || FalseVal !=
RHS)
13275 EVT LeftType =
LHS->getValueType(0);
13276 EVT RightType =
RHS->getValueType(0);
13279 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13283 if (VectorScalarType != MVT::i32)
13291 if (VectorScalarType != MVT::i32)
13304 EVT VT =
N->getValueType(0);
13312 Shft =
N->getOperand(0);
13319 Cmp.getOperand(0) !=
N->getOperand(1) ||
13320 Cmp.getOperand(1) !=
N->getOperand(2))
13322 Shft =
N->getOperand(1);
13334 ScalarType = MVT::i8;
13337 case (1 << 15) - 1:
13338 ScalarType = MVT::i16;
13341 case (1ULL << 31) - 1:
13342 ScalarType = MVT::i32;
13373 unsigned LegalLanes = 128 / (ShftAmt + 1);
13397 for (
unsigned I = 0;
I < NumParts; ++
I) {
13414 if (!Subtarget->hasMVEIntegerOps())
13429 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13439 if (!Const || !Const->isOne())
13457 EVT VT =
N->getValueType(0);
13459 if (!Subtarget->hasMVEIntegerOps() ||
13488 Opc = Intrinsic::arm_mve_vctp64;
13491 Opc = Intrinsic::arm_mve_vctp32;
13494 Opc = Intrinsic::arm_mve_vctp16;
13497 Opc = Intrinsic::arm_mve_vctp8;
13551 EVT VT =
N->getValueType(0);
13557 switch (
Op.getOpcode()) {
13558 case ISD::VECREDUCE_ADD:
13582 unsigned N0RedOp = 0;
13589 unsigned N1RedOp = 0;
13603 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13605 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13612 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13636 if (!BaseLocDecomp0.getBase() ||
13637 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13638 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13640 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13642 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13652 if (IsBefore < 0) {
13655 }
else if (IsBefore > 0) {
13668 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13678 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13688 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13690 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13697 if (!Subtarget->hasMVEIntegerOps())
13703 EVT VT =
N->getValueType(0);
13708 if (VT != MVT::i64)
13719 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13739 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13788 "Expected shift op");
13790 SDValue ShiftLHS =
N->getOperand(0);
13804 if (Subtarget->isThumb1Only()) {
13815 if (Const->getAPIntValue().ult(256))
13818 Const->getAPIntValue().sgt(-256))
13834 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13835 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13836 "Expected XOR(SHIFT) pattern");
13841 if (XorC && ShiftC) {
13842 unsigned MaskIdx, MaskLen;
13843 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13844 unsigned ShiftAmt = ShiftC->getZExtValue();
13845 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13846 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13847 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13848 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13858 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13860 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13861 "Expected shift-shift mask");
13863 if (!Subtarget->isThumb1Only())
13866 EVT VT =
N->getValueType(0);
13874 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13876 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13881 if (!Subtarget->hasNEON()) {
13882 if (Subtarget->isThumb1Only())
13896 return Subtarget->hasVFP2Base();
13898 return Subtarget->hasVFP2Base();
13900 return Subtarget->hasFP64();
13903 return Subtarget->hasMVEFloatOps();
13932 if (ST->isThumb() && ST->isThumb1Only())
13936 for (
auto *U :
N->users()) {
13937 switch(U->getOpcode()) {
13955 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13956 U->getOperand(1).getOpcode() ==
ISD::SHL)
13966 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13973 if (!C1ShlC2 || !C2)
13976 APInt C2Int = C2->getAPIntValue();
13977 APInt C1Int = C1ShlC2->getAPIntValue();
13979 if (C2Int.
uge(C2Width))
13985 if ((C1Int & Mask) != C1Int)
13992 auto LargeImm = [](
const APInt &Imm) {
13993 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13994 return Imm.getBitWidth() - Zeros > 8;
13997 if (LargeImm(C1Int) || LargeImm(C2Int))
14009 SHL.dump();
N->dump());
14044 if (CSINC.getOpcode() !=
ARMISD::CSINC || !CSINC.hasOneUse())
14053 CSINC.getOperand(0)),
14054 CSINC.getOperand(1), CSINC.getOperand(2),
14055 CSINC.getOperand(3));
14112 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14154 if (!Subtarget->hasVMLxForwarding())
14173 EVT VT =
N->getValueType(0);
14184 EVT VT =
N->getValueType(0);
14185 if (VT != MVT::v2i64)
14196 return Op->getOperand(0);
14209 if (
And->getOpcode() == ISD::BITCAST)
14210 And =
And->getOperand(0);
14214 if (Mask->getOpcode() == ISD::BITCAST)
14215 Mask = Mask->getOperand(0);
14218 Mask.getValueType() != MVT::v4i32)
14224 return And->getOperand(0);
14229 if (
SDValue Op0 = IsSignExt(N0)) {
14230 if (
SDValue Op1 = IsSignExt(N1)) {
14236 if (
SDValue Op0 = IsZeroExt(N0)) {
14237 if (
SDValue Op1 = IsZeroExt(N1)) {
14252 EVT VT =
N->getValueType(0);
14253 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14264 if (VT != MVT::i32)
14271 int64_t MulAmt =
C->getSExtValue();
14274 ShiftAmt = ShiftAmt & (32 - 1);
14279 MulAmt >>= ShiftAmt;
14340 if (
N->getValueType(0) != MVT::i32)
14349 if (C1 == 255 || C1 == 65535)
14352 SDNode *N0 =
N->getOperand(0).getNode();
14366 if (!C2 || C2 >= 32)
14410 if (Trailing == C2 && C2 + C3 < 32) {
14423 if (Leading == C2 && C2 + C3 < 32) {
14451 EVT VT =
N->getValueType(0);
14455 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14458 APInt SplatBits, SplatUndef;
14459 unsigned SplatBitSize;
14461 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14462 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14463 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14464 SplatBitSize == 64) {
14498 if (!Subtarget->hasV6Ops() ||
14499 (Subtarget->isThumb() &&
14500 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14503 SDValue SRL = OR->getOperand(0);
14504 SDValue SHL = OR->getOperand(1);
14507 SRL = OR->getOperand(1);
14508 SHL = OR->getOperand(0);
14515 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14519 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14520 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14521 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14540 unsigned Opcode = 0;
14541 if (
isS16(OpS16, DAG))
14559 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14562 EVT VT =
N->getValueType(0);
14577 if (VT != MVT::i32)
14590 if (Mask == 0xffff)
14597 if ((Val & ~Mask) != Val)
14622 (Mask == ~Mask2)) {
14625 if (Subtarget->hasDSP() &&
14626 (Mask == 0xffff || Mask == 0xffff0000))
14639 (~Mask == Mask2)) {
14642 if (Subtarget->hasDSP() &&
14643 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14709 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14716 EVT VT =
N->getValueType(0);
14721 auto IsFreelyInvertable = [&](
SDValue V) {
14728 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14744 EVT VT =
N->getValueType(0);
14750 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14751 VT == MVT::v8i1 || VT == MVT::v16i1))
14754 APInt SplatBits, SplatUndef;
14755 unsigned SplatBitSize;
14757 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14758 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14759 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14760 SplatBitSize == 64) {
14796 unsigned SplatBitSize;
14799 APInt SplatBits0, SplatBits1;
14803 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14804 HasAnyUndefs) && !HasAnyUndefs) {
14805 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14806 HasAnyUndefs) && !HasAnyUndefs) {
14811 SplatBits0 == ~SplatBits1) {
14841 EVT VT =
N->getValueType(0);
14856 if (Subtarget->hasMVEIntegerOps()) {
14887 ToMask =
~N->getConstantOperandAPInt(2);
14907 unsigned LastActiveBitInA =
A.countr_zero();
14908 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14909 return LastActiveBitInA - 1 == FirstActiveBitInB;
14914 APInt ToMask, FromMask;
14922 APInt NewToMask, NewFromMask;
14924 if (NewFrom != From)
14928 if ((NewToMask & ToMask).getBoolValue())
14953 unsigned InvMask =
N->getConstantOperandVal(2);
14957 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14958 "undefined behavior");
14959 unsigned Mask = (1u << Width) - 1;
14961 if ((Mask & (~Mask2)) == 0)
14963 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14970 APInt ToMask1, FromMask1;
14973 APInt ToMask2, FromMask2;
14979 APInt NewFromMask = FromMask1 | FromMask2;
14980 APInt NewToMask = ToMask1 | ToMask2;
14982 EVT VT =
N->getValueType(0);
14985 if (NewFromMask[0] == 0)
14997 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14998 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
15000 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
15004 EVT VT =
N->getValueType(0);
15007 N->getOperand(1),
N->getOperand(2));
15021 SDValue CSInc = Cmp->getOperand(0);
15071 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15072 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15075 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15077 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15090 SDValue InDouble =
N->getOperand(0);
15105 SDValue BasePtr = LD->getBasePtr();
15107 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15108 LD->getAlign(), LD->getMemOperand()->getFlags());
15114 LD->getPointerInfo().getWithOffset(4),
15116 LD->getMemOperand()->getFlags());
15132 bool BVSwap = BV.
getOpcode() == ISD::BITCAST;
15137 BVSwap = BV.
getOpcode() == ISD::BITCAST;
15149 if (!Subtarget->
isLittle() && BVSwap)
15167 if (!Subtarget->
isLittle() && BVSwap)
15210 if (Op0->
getOpcode() == ISD::BITCAST) {
15212 if (Copy.getValueType() == MVT::f32 &&
15214 bool HasGlue = Copy->getNumOperands() == 3;
15215 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15216 HasGlue ? Copy->getOperand(2) :
SDValue()};
15217 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15236 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15237 LN0->getMemoryVT() == MVT::i16) {
15240 LN0->getBasePtr(), LN0->getMemOperand());
15258 EVT VT =
N->getValueType(0);
15292 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15293 for (
unsigned i = 0; i < NumElts; ++i) {
15294 SDNode *Elt =
N->getOperand(i).getNode();
15311 if (
N->getNumOperands() == 2)
15317 EVT VT =
N->getValueType(0);
15323 for (
unsigned i = 0; i < NumElts; ++i) {
15324 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(i));
15331 return DAG.
getNode(ISD::BITCAST, dl, VT, BV);
15349 EVT VT =
N->getValueType(0);
15357 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15361 if (
Use->getOpcode() != ISD::BITCAST ||
15362 Use->getValueType(0).isFloatingPoint())
15370 unsigned NumOfBitCastedElts = 0;
15372 unsigned NumOfRelevantElts = NumElts;
15373 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15375 if (Elt->
getOpcode() == ISD::BITCAST) {
15378 ++NumOfBitCastedElts;
15382 --NumOfRelevantElts;
15386 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15404 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15408 if (V.getOpcode() == ISD::BITCAST &&
15409 V->getOperand(0).getValueType() == MVT::i32)
15411 V = V.getOperand(0);
15420 Vec = DAG.
getNode(ISD::BITCAST, dl, VT, Vec);
15428 EVT VT =
N->getValueType(0);
15435 if (
Op->getOperand(0).getValueType() == VT)
15436 return Op->getOperand(0);
15451 if (
Op.getValueType() == MVT::i32) {
15462 EVT VT =
N->getValueType(0);
15467 if (ST->isLittle())
15468 return DAG.
getNode(ISD::BITCAST, dl, VT,
Op);
15471 if (
Op.getValueType() == VT)
15480 if (
Op->getOperand(0).getValueType() == VT)
15481 return Op->getOperand(0);
15490 if (!Subtarget->hasMVEIntegerOps())
15493 EVT VT =
N->getValueType(0);
15524 EVT VT =
N->getValueType(0);
15525 SDNode *Elt =
N->getOperand(1).getNode();
15534 SDValue Vec = DAG.
getNode(ISD::BITCAST, dl, FloatVT,
N->getOperand(0));
15535 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(1));
15540 Vec, V,
N->getOperand(2));
15541 return DAG.
getNode(ISD::BITCAST, dl, VT, InsElt);
15550 EVT VT =
N->getValueType(0);
15558 if (Ext.getOpcode() == ISD::BITCAST &&
15559 Ext.getOperand(0).getValueType() == MVT::f32)
15560 Ext = Ext.getOperand(0);
15563 Ext.getConstantOperandVal(1) % 2 != 0)
15565 if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() ==
ISD::SINT_TO_FP ||
15569 SDValue Op0 = Ext.getOperand(0);
15572 unsigned Lane = Ext.getConstantOperandVal(1);
15578 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15579 isa<ConstantSDNode>(V->getOperand(1)) &&
15580 V->getConstantOperandVal(1) == Lane + 1 &&
15581 V->getOperand(0).getResNo() == ResNo;
15583 if (OtherIt == Op0->
users().
end())
15588 SDValue OtherExt(*OtherIt, 0);
15601 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15613 EVT VT =
N->getValueType(0);
15619 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15621 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15623 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15626 while (
X.getValueType() != VT &&
X->getOpcode() == ISD::BITCAST)
15627 X =
X->getOperand(0);
15628 if (
X.getValueType() == VT)
15636 return Op0.
getOperand(
N->getConstantOperandVal(1));
15646 unsigned Offset =
N->getConstantOperandVal(1);
15658 unsigned Idx =
N->getConstantOperandVal(1);
15672 EVT VT =
N->getValueType(0);
15677 Op.getOperand(0).getValueType().getScalarType())
15687 SDValue SubVec =
N->getOperand(1);
15688 uint64_t IdxVal =
N->getConstantOperandVal(2);
15699 if (IdxVal == 0 && Vec.
isUndef())
15705 (IdxVal != 0 && IdxVal != NumSubElts))
15778 EVT VT =
N->getValueType(0);
15789 unsigned HalfElts = NumElts/2;
15791 for (
unsigned n = 0; n < NumElts; ++n) {
15794 if (MaskElt < (
int)HalfElts)
15796 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15797 NewElt = HalfElts + MaskElt - NumElts;
15840 bool SimpleConstIncOnly,
15848 bool isLoadOp =
true;
15849 bool isLaneOp =
false;
15852 bool hasAlignment =
true;
15853 unsigned NewOpc = 0;
15854 unsigned NumVecs = 0;
15855 if (
Target.isIntrinsic) {
15856 unsigned IntNo =
N->getConstantOperandVal(1);
15860 case Intrinsic::arm_neon_vld1:
15864 case Intrinsic::arm_neon_vld2:
15868 case Intrinsic::arm_neon_vld3:
15872 case Intrinsic::arm_neon_vld4:
15876 case Intrinsic::arm_neon_vld1x2:
15879 hasAlignment =
false;
15881 case Intrinsic::arm_neon_vld1x3:
15884 hasAlignment =
false;
15886 case Intrinsic::arm_neon_vld1x4:
15889 hasAlignment =
false;
15891 case Intrinsic::arm_neon_vld2dup:
15895 case Intrinsic::arm_neon_vld3dup:
15899 case Intrinsic::arm_neon_vld4dup:
15903 case Intrinsic::arm_neon_vld2lane:
15908 case Intrinsic::arm_neon_vld3lane:
15913 case Intrinsic::arm_neon_vld4lane:
15918 case Intrinsic::arm_neon_vst1:
15923 case Intrinsic::arm_neon_vst2:
15928 case Intrinsic::arm_neon_vst3:
15933 case Intrinsic::arm_neon_vst4:
15938 case Intrinsic::arm_neon_vst2lane:
15944 case Intrinsic::arm_neon_vst3lane:
15950 case Intrinsic::arm_neon_vst4lane:
15956 case Intrinsic::arm_neon_vst1x2:
15960 hasAlignment =
false;
15962 case Intrinsic::arm_neon_vst1x3:
15966 hasAlignment =
false;
15968 case Intrinsic::arm_neon_vst1x4:
15972 hasAlignment =
false;
15977 switch (
N->getOpcode()) {
16013 VecTy =
N->getValueType(0);
16014 }
else if (
Target.isIntrinsic) {
16015 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16018 "Node has to be a load, a store, or an intrinsic!");
16019 VecTy =
N->getOperand(1).getValueType();
16027 if (isLaneOp || isVLDDUPOp)
16030 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16036 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16045 EVT AlignedVecTy = VecTy;
16065 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16066 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16077 Alignment =
Align(1);
16083 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16085 for (n = 0; n < NumResultVecs; ++n)
16086 Tys[n] = AlignedVecTy;
16087 Tys[n++] = MVT::i32;
16088 Tys[n] = MVT::Other;
16093 Ops.push_back(
N->getOperand(0));
16094 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16099 Ops.push_back(StN->getValue());
16103 unsigned LastOperand =
16104 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16105 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16106 Ops.push_back(
N->getOperand(i));
16114 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::STORE) {
16116 StVal = DAG.
getNode(ISD::BITCAST, dl, AlignedVecTy, StVal);
16125 for (
unsigned i = 0; i < NumResultVecs; ++i)
16130 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::LOAD) {
16131 SDValue &LdVal = NewResults[0];
16132 LdVal = DAG.
getNode(ISD::BITCAST, dl, VecTy, LdVal);
16167 switch (
N->getOpcode()) {
16171 *
Ptr =
N->getOperand(0);
16172 *CInc =
N->getOperand(1);
16179 *
Ptr =
N->getOperand(1);
16180 *CInc =
N->getOperand(2);
16199 const bool isStore =
N->getOpcode() == ISD::STORE;
16207 SDValue Addr =
N->getOperand(AddrOpIdx);
16218 unsigned ConstInc =
16223 if (BaseUpdates.
size() >= MaxBaseUpdates)
16243 unsigned UserOffset =
16246 if (!UserOffset || UserOffset <=
Offset)
16249 unsigned NewConstInc = UserOffset -
Offset;
16252 if (BaseUpdates.
size() >= MaxBaseUpdates)
16259 unsigned NumValidUpd = BaseUpdates.
size();
16260 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16271 return LHS.ConstInc <
RHS.ConstInc;
16300 unsigned IntNo =
N->getConstantOperandVal(1);
16301 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16303 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16326 bool isLoadOp =
true;
16327 unsigned NewOpc = 0;
16328 unsigned NumVecs = 0;
16332 case Intrinsic::arm_mve_vld2q:
16336 case Intrinsic::arm_mve_vld4q:
16340 case Intrinsic::arm_mve_vst2q:
16345 case Intrinsic::arm_mve_vst4q:
16355 VecTy =
N->getValueType(0);
16357 VecTy =
N->getOperand(3).getValueType();
16371 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16373 for (n = 0; n < NumResultVecs; ++n)
16375 Tys[n++] = MVT::i32;
16376 Tys[n] = MVT::Other;
16381 Ops.push_back(
N->getOperand(0));
16382 Ops.push_back(
N->getOperand(2));
16383 Ops.push_back(Inc);
16385 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16386 Ops.push_back(
N->getOperand(i));
16393 for (
unsigned i = 0; i < NumResultVecs; ++i)
16412 EVT VT =
N->getValueType(0);
16418 SDNode *VLD =
N->getOperand(0).getNode();
16421 unsigned NumVecs = 0;
16422 unsigned NewOpc = 0;
16424 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16427 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16430 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16442 if (
Use.getResNo() == NumVecs)
16446 VLDLaneNo !=
User->getConstantOperandVal(1))
16453 for (n = 0; n < NumVecs; ++n)
16455 Tys[n] = MVT::Other;
16465 unsigned ResNo =
Use.getResNo();
16467 if (ResNo == NumVecs)
16474 std::vector<SDValue> VLDDupResults;
16475 for (
unsigned n = 0; n < NumVecs; ++n)
16489 EVT VT =
N->getValueType(0);
16492 if (Subtarget->hasMVEIntegerOps()) {
16496 ExtractVT = MVT::i32;
16498 N->getOperand(0),
N->getOperand(1));
16509 while (
Op.getOpcode() == ISD::BITCAST)
16510 Op =
Op.getOperand(0);
16515 unsigned EltSize =
Op.getScalarValueSizeInBits();
16517 unsigned Imm =
Op.getConstantOperandVal(0);
16533 if (Subtarget->hasMVEIntegerOps()) {
16536 if (
Op.getValueType() == MVT::f32)
16538 DAG.
getNode(ISD::BITCAST, dl, MVT::i32,
Op));
16539 else if (
Op.getValueType() == MVT::f16)
16544 if (!Subtarget->hasNEON())
16551 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16552 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16553 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16558 LD->getMemoryVT(), LD->getMemOperand());
16569 EVT VT =
N->getValueType(0);
16591 assert(StVT != VT &&
"Cannot truncate to the same type");
16601 if (0 != (NumElems * FromEltSz) % ToEltSz)
16604 unsigned SizeRatio = FromEltSz / ToEltSz;
16609 NumElems * SizeRatio);
16615 for (
unsigned i = 0; i < NumElems; ++i)
16629 MVT StoreType = MVT::i8;
16631 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16651 for (
unsigned I = 0;
I <
E;
I++) {
16682 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16685 unsigned NumElements = 4;
16702 unsigned Off0 = Rev ? NumElts : 0;
16703 unsigned Off1 = Rev ? 0 : NumElts;
16705 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16706 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16708 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16716 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16736 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16751 NewToVT, Alignment, MMOFlags, AAInfo);
16784 unsigned NewOffset =
16792 NewToVT, Alignment, MMOFlags, AAInfo);
16814 {Extract.getOperand(0), Extract.getOperand(1)});
16845 if (Subtarget->hasNEON())
16849 if (Subtarget->hasMVEFloatOps())
16853 if (Subtarget->hasMVEIntegerOps()) {
16928 if (!Subtarget->hasNEON())
16932 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16940 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16942 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16943 uint32_t IntBits = IntTy.getSizeInBits();
16944 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16945 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16956 if (
C == -1 ||
C == 0 ||
C > 32)
16961 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16962 Intrinsic::arm_neon_vcvtfp2fxu;
16965 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16968 if (IntBits < FloatBits)
16976 if (!Subtarget->hasMVEFloatOps())
16984 EVT VT =
N->getValueType(0);
16989 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16990 if (
Op.getOpcode() != ISD::BITCAST ||
16993 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16994 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16996 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17009 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17020 EVT VT =
N->getValueType(0);
17023 if (!
N->getFlags().hasAllowReassociation())
17030 unsigned Opc =
A.getConstantOperandVal(0);
17031 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17036 A.getOperand(3),
A.getOperand(4));
17068 if (!Subtarget->hasNEON())
17072 unsigned OpOpcode =
Op.getNode()->getOpcode();
17073 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17077 SDValue ConstVec =
N->getOperand(1);
17081 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17083 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17084 uint32_t IntBits = IntTy.getSizeInBits();
17085 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17086 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17106 int32_t
C = IntVal.exactLogBase2();
17107 if (
C == -1 ||
C == 0 ||
C > 32)
17113 if (IntBits < FloatBits)
17115 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17117 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17118 : Intrinsic::arm_neon_vcvtfxu2fp;
17126 if (!ST->hasMVEIntegerOps())
17129 assert(
N->getOpcode() == ISD::VECREDUCE_ADD);
17130 EVT ResVT =
N->getValueType(0);
17158 EVT AVT =
A.getValueType();
17164 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17165 EVT AVT =
A.getValueType();
17173 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17174 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17177 if (ExtTypeMatches(
A, ExtTypes))
17178 return ExtendIfNeeded(
A, ExtendCode);
17181 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17188 if (Ext->getOpcode() != ExtendCode)
17191 if (ExtTypeMatches(
A, ExtTypes))
17192 return ExtendIfNeeded(
A, ExtendCode);
17195 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17205 if (ResVT != RetTy)
17208 if (
Mul->getOpcode() == ExtendCode &&
17209 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17211 Mul =
Mul->getOperand(0);
17220 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17221 A = ExtendIfNeeded(
A, ExtendCode);
17222 B = ExtendIfNeeded(
B, ExtendCode);
17227 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17240 if (
Mul->getOpcode() == ExtendCode &&
17241 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17243 Mul =
Mul->getOperand(0);
17252 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17253 A = ExtendIfNeeded(
A, ExtendCode);
17254 B = ExtendIfNeeded(
B, ExtendCode);
17265 EVT VT =
Ops[0].getValueType();
17266 if (VT == MVT::v16i8) {
17268 "Unexpected illegal long reduction opcode");
17297 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17300 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17364 Op =
Op->getOperand(1);
17366 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17368 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17374 return DAG.
getNode(ISD::VECREDUCE_ADD, dl, ResVT, Ext);
17385 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17387 if (!Shuf || !Shuf->getOperand(1).isUndef())
17392 APInt SetElts(Mask.size(), 0);
17393 for (
int E : Mask) {
17401 if (
N->getNumOperands() != VecOp + 1) {
17403 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17409 if (
Op.getValueType().isVector())
17410 Ops.push_back(
Op.getOperand(0));
17421 unsigned IsTop =
N->getConstantOperandVal(2);
17428 if (Op0->
isUndef() && !IsTop)
17442 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17444 APInt Op0DemandedElts =
17445 IsTop ? Op1DemandedElts
17460 unsigned IsTop =
N->getConstantOperandVal(2);
17462 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17463 APInt Op0DemandedElts =
17475 EVT VT =
N->getValueType(0);
17482 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17483 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17487 LHS.getOperand(0),
RHS.getOperand(0));
17502 int ShiftAmt =
C->getSExtValue();
17503 if (ShiftAmt == 0) {
17509 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17510 unsigned NewOpcode =
17526 unsigned IntNo =
N->getConstantOperandVal(0);
17537 case Intrinsic::arm_neon_vshifts:
17538 case Intrinsic::arm_neon_vshiftu:
17539 case Intrinsic::arm_neon_vrshifts:
17540 case Intrinsic::arm_neon_vrshiftu:
17541 case Intrinsic::arm_neon_vrshiftn:
17542 case Intrinsic::arm_neon_vqshifts:
17543 case Intrinsic::arm_neon_vqshiftu:
17544 case Intrinsic::arm_neon_vqshiftsu:
17545 case Intrinsic::arm_neon_vqshiftns:
17546 case Intrinsic::arm_neon_vqshiftnu:
17547 case Intrinsic::arm_neon_vqshiftnsu:
17548 case Intrinsic::arm_neon_vqrshiftns:
17549 case Intrinsic::arm_neon_vqrshiftnu:
17550 case Intrinsic::arm_neon_vqrshiftnsu: {
17551 EVT VT =
N->getOperand(1).getValueType();
17553 unsigned VShiftOpc = 0;
17556 case Intrinsic::arm_neon_vshifts:
17557 case Intrinsic::arm_neon_vshiftu:
17562 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17569 case Intrinsic::arm_neon_vrshifts:
17570 case Intrinsic::arm_neon_vrshiftu:
17575 case Intrinsic::arm_neon_vqshifts:
17576 case Intrinsic::arm_neon_vqshiftu:
17581 case Intrinsic::arm_neon_vqshiftsu:
17586 case Intrinsic::arm_neon_vrshiftn:
17587 case Intrinsic::arm_neon_vqshiftns:
17588 case Intrinsic::arm_neon_vqshiftnu:
17589 case Intrinsic::arm_neon_vqshiftnsu:
17590 case Intrinsic::arm_neon_vqrshiftns:
17591 case Intrinsic::arm_neon_vqrshiftnu:
17592 case Intrinsic::arm_neon_vqrshiftnsu:
17604 case Intrinsic::arm_neon_vshifts:
17605 case Intrinsic::arm_neon_vshiftu:
17608 case Intrinsic::arm_neon_vrshifts:
17611 case Intrinsic::arm_neon_vrshiftu:
17614 case Intrinsic::arm_neon_vrshiftn:
17617 case Intrinsic::arm_neon_vqshifts:
17620 case Intrinsic::arm_neon_vqshiftu:
17623 case Intrinsic::arm_neon_vqshiftsu:
17626 case Intrinsic::arm_neon_vqshiftns:
17629 case Intrinsic::arm_neon_vqshiftnu:
17632 case Intrinsic::arm_neon_vqshiftnsu:
17635 case Intrinsic::arm_neon_vqrshiftns:
17638 case Intrinsic::arm_neon_vqrshiftnu:
17641 case Intrinsic::arm_neon_vqrshiftnsu:
17647 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17648 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17651 case Intrinsic::arm_neon_vshiftins: {
17652 EVT VT =
N->getOperand(1).getValueType();
17654 unsigned VShiftOpc = 0;
17658 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17665 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17666 N->getOperand(1),
N->getOperand(2),
17670 case Intrinsic::arm_neon_vqrshifts:
17671 case Intrinsic::arm_neon_vqrshiftu:
17675 case Intrinsic::arm_neon_vbsl: {
17678 N->getOperand(2),
N->getOperand(3));
17680 case Intrinsic::arm_mve_vqdmlah:
17681 case Intrinsic::arm_mve_vqdmlash:
17682 case Intrinsic::arm_mve_vqrdmlah:
17683 case Intrinsic::arm_mve_vqrdmlash:
17684 case Intrinsic::arm_mve_vmla_n_predicated:
17685 case Intrinsic::arm_mve_vmlas_n_predicated:
17686 case Intrinsic::arm_mve_vqdmlah_predicated:
17687 case Intrinsic::arm_mve_vqdmlash_predicated:
17688 case Intrinsic::arm_mve_vqrdmlah_predicated:
17689 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17694 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17701 case Intrinsic::arm_mve_minv:
17702 case Intrinsic::arm_mve_maxv:
17703 case Intrinsic::arm_mve_minav:
17704 case Intrinsic::arm_mve_maxav:
17705 case Intrinsic::arm_mve_minv_predicated:
17706 case Intrinsic::arm_mve_maxv_predicated:
17707 case Intrinsic::arm_mve_minav_predicated:
17708 case Intrinsic::arm_mve_maxav_predicated: {
17711 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17718 case Intrinsic::arm_mve_addv: {
17721 bool Unsigned =
N->getConstantOperandVal(2);
17726 case Intrinsic::arm_mve_addlv:
17727 case Intrinsic::arm_mve_addlv_predicated: {
17730 bool Unsigned =
N->getConstantOperandVal(2);
17731 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17736 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17738 Ops.push_back(
N->getOperand(i));
17759 EVT VT =
N->getValueType(0);
17761 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17762 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17763 N->getOperand(0)->hasOneUse()) {
17780 if (AndMask == 255 || AndMask == 65535)
17784 if (MaskedBits > ShiftAmt) {
17799 if (ST->hasMVEIntegerOps())
17804 switch (
N->getOpcode()) {
17817 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17818 unsigned VShiftOpc =
17821 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17837 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17840 EVT FromVT = LD->getValueType(0);
17841 EVT ToVT =
N->getValueType(0);
17848 unsigned NumElements = 0;
17849 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17851 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17853 if (NumElements == 0 ||
17863 SDValue BasePtr = LD->getBasePtr();
17864 Align Alignment = LD->getBaseAlign();
17885 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17886 Alignment, MMOFlags, AAInfo);
17892 if (FromEltVT == MVT::f16) {
17895 for (
unsigned i = 0; i < Loads.
size(); i++) {
17921 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17925 EVT VT =
N->getValueType(0);
17929 if (VT == MVT::i32 &&
17930 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17935 switch (
N->getOpcode()) {
17949 if (ST->hasMVEIntegerOps())
17958 if (ST->hasMVEFloatOps())
17969 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17973 EVT VT =
Op.getValueType();
17976 if (VT != MVT::i32 ||
17989 APInt MaxC = Max.getConstantOperandAPInt(1);
17992 !(MinC + 1).isPowerOf2())
18010 EVT VT =
N->getValueType(0);
18013 if (VT == MVT::i32)
18016 if (!ST->hasMVEIntegerOps())
18022 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18025 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18033 if (VT == MVT::v4i32)
18034 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18036 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18043 MaxC != ~SaturateC)
18048 if (IsSignedSaturate(
N, N0.
getNode())) {
18051 if (VT == MVT::v4i32) {
18052 HalfVT = MVT::v8i16;
18053 ExtVT = MVT::v4i16;
18055 HalfVT = MVT::v16i8;
18070 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18076 if (VT == MVT::v4i32)
18077 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18079 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18088 if (IsUnsignedSaturate(
N)) {
18092 if (VT == MVT::v4i32) {
18093 HalfVT = MVT::v8i16;
18094 ExtConst = 0x0000FFFF;
18096 HalfVT = MVT::v16i8;
18118 const APInt *CV = &
C->getAPIntValue();
18136 SDValue Op0 = CMOV->getOperand(0);
18137 SDValue Op1 = CMOV->getOperand(1);
18138 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
18139 SDValue CmpZ = CMOV->getOperand(3);
18175 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18182 if ((OrCI & Known.
Zero) != OrCI)
18188 EVT VT =
X.getValueType();
18189 unsigned BitInX = AndC->
logBase2();
18197 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18198 BitInY < NumActiveBits; ++BitInY) {
18199 if (OrCI[BitInY] == 0)
18202 Mask.setBit(BitInY);
18219 switch (
N->getOpcode()) {
18234 if (Const->isZero())
18236 else if (Const->isOne())
18244 unsigned IntOp =
N.getConstantOperandVal(1);
18245 if (IntOp != Intrinsic::test_start_loop_iterations &&
18246 IntOp != Intrinsic::loop_decrement_reg)
18272 bool Negate =
false;
18276 if (
N->getOpcode() == ISD::BRCOND) {
18278 Cond =
N->getOperand(1);
18279 Dest =
N->getOperand(2);
18281 assert(
N->getOpcode() == ISD::BR_CC &&
"Expected BRCOND or BR_CC!");
18283 Cond =
N->getOperand(2);
18284 Dest =
N->getOperand(4);
18286 if (!Const->isOne() && !Const->isZero())
18288 Imm = Const->getZExtValue();
18316 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18317 "unsupported condition");
18322 unsigned IntOp =
Int->getConstantOperandVal(1);
18323 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() == ISD::BR) &&
18324 "expected single br user");
18325 SDNode *Br = *
N->user_begin();
18335 if (IntOp == Intrinsic::test_start_loop_iterations) {
18339 if (IsTrueIfZero(CC, Imm)) {
18345 UpdateUncondBr(Br, Dest, DAG);
18347 SDValue Ops[] = {Chain, Setup, OtherTarget};
18360 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18364 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18368 if (
Target == OtherTarget)
18369 UpdateUncondBr(Br, Dest, DAG);
18389 SDValue LHS = Cmp.getOperand(0);
18390 SDValue RHS = Cmp.getOperand(1);
18400 LHS->getOperand(0)->hasOneUse() &&
18420 EVT VT =
N->getValueType(0);
18422 SDValue LHS = Cmp.getOperand(0);
18423 SDValue RHS = Cmp.getOperand(1);
18424 SDValue FalseVal =
N->getOperand(0);
18425 SDValue TrueVal =
N->getOperand(1);
18430 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18454 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18456 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18468 LHS->getOperand(2), LHS->getOperand(3));
18478 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18482 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18484 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18493 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18558 const APInt *TrueConst;
18559 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18560 ((FalseVal.getOpcode() ==
ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18561 FalseVal.getOperand(1) == RHS) ||
18565 unsigned ShiftAmount = TrueConst->
logBase2();
18580 if (Known.
Zero == 0xfffffffe)
18583 else if (Known.
Zero == 0xffffff00)
18586 else if (Known.
Zero == 0xffff0000)
18599 EVT DstVT =
N->getValueType(0);
18602 if (ST->hasMVEIntegerOps() && Src.getOpcode() ==
ARMISD::VDUP) {
18603 EVT SrcVT = Src.getValueType();
18611 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18612 Src.getValueType().getScalarSizeInBits())
18613 Src = Src.getOperand(0);
18617 EVT SrcVT = Src.getValueType();
18637 EVT VT =
N->getValueType(0);
18645 if (
N->getNumOperands() == 2 &&
18649 N->getOperand(0).getOperand(1),
18650 N->getOperand(1).getOperand(0),
18651 N->getOperand(1).getOperand(1));
18654 if (
N->getNumOperands() == 2 &&
18660 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18661 S0->getOperand(1) ==
S1->getOperand(1)) {
18664 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18684 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18685 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18686 (Op.getOpcode() == ISD::BITCAST &&
18687 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18690 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18692 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18710 int NumIns =
N->getNumOperands();
18711 assert((NumIns == 2 || NumIns == 4) &&
18712 "Expected 2 or 4 inputs to an MVETrunc");
18714 if (
N->getNumOperands() == 4)
18718 for (
int I = 0;
I < NumIns;
I++) {
18720 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18740 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18743 EVT FromVT = LD->getMemoryVT();
18744 EVT ToVT =
N->getValueType(0);
18751 unsigned NumElements = 0;
18752 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18754 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18756 assert(NumElements != 0);
18762 LD->getExtensionType() != NewExtType)
18769 SDValue BasePtr = LD->getBasePtr();
18770 Align Alignment = LD->getBaseAlign();
18789 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18790 Alignment, MMOFlags, AAInfo);
18806 EVT VT =
N->getValueType(0);
18808 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18809 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18811 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18813 auto Extend = [&](
SDValue V) {
18823 SDValue Ext = Extend(
N->getOperand(0));
18831 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18836 auto CheckInregMask = [&](
int Start,
int Offset) {
18838 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18844 if (CheckInregMask(0, 0))
18846 else if (CheckInregMask(0, 1))
18847 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18848 else if (CheckInregMask(0, Mask.size()))
18850 else if (CheckInregMask(0, Mask.size() + 1))
18851 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18856 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18860 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18867 if (
N->getOperand(0)->getOpcode() == ISD::LOAD)
18878 int NumOuts =
N->getNumValues();
18879 assert((NumOuts == 2 || NumOuts == 4) &&
18880 "Expected 2 or 4 outputs to an MVEEXT");
18881 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18883 if (
N->getNumOperands() == 4)
18889 StackPtr, MPI,
Align(4));
18892 for (
int I = 0;
I < NumOuts;
I++) {
18894 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18895 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18900 VT, Chain,
Ptr, MPI, LoadVT,
Align(4));
18909 switch (
N->getOpcode()) {
18960 case ISD::FP_EXTEND:
18999 case ISD::VECREDUCE_ADD:
19026 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19033 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19044 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19052 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19054 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19062 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19064 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19072 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19083 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19091 if (
N->getOperand(1) ==
N->getOperand(2))
19092 return N->getOperand(1);
19096 switch (
N->getConstantOperandVal(1)) {
19097 case Intrinsic::arm_neon_vld1:
19098 case Intrinsic::arm_neon_vld1x2:
19099 case Intrinsic::arm_neon_vld1x3:
19100 case Intrinsic::arm_neon_vld1x4:
19101 case Intrinsic::arm_neon_vld2:
19102 case Intrinsic::arm_neon_vld3:
19103 case Intrinsic::arm_neon_vld4:
19104 case Intrinsic::arm_neon_vld2lane:
19105 case Intrinsic::arm_neon_vld3lane:
19106 case Intrinsic::arm_neon_vld4lane:
19107 case Intrinsic::arm_neon_vld2dup:
19108 case Intrinsic::arm_neon_vld3dup:
19109 case Intrinsic::arm_neon_vld4dup:
19110 case Intrinsic::arm_neon_vst1:
19111 case Intrinsic::arm_neon_vst1x2:
19112 case Intrinsic::arm_neon_vst1x3:
19113 case Intrinsic::arm_neon_vst1x4:
19114 case Intrinsic::arm_neon_vst2:
19115 case Intrinsic::arm_neon_vst3:
19116 case Intrinsic::arm_neon_vst4:
19117 case Intrinsic::arm_neon_vst2lane:
19118 case Intrinsic::arm_neon_vst3lane:
19119 case Intrinsic::arm_neon_vst4lane:
19121 case Intrinsic::arm_mve_vld2q:
19122 case Intrinsic::arm_mve_vld4q:
19123 case Intrinsic::arm_mve_vst2q:
19124 case Intrinsic::arm_mve_vst4q:
19135 return (VT == MVT::f32) && (
Opc == ISD::LOAD ||
Opc == ISD::STORE);
19141 unsigned *
Fast)
const {
19147 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19150 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19152 if (AllowsUnaligned) {
19154 *
Fast = Subtarget->hasV7Ops();
19159 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19163 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19170 if (!Subtarget->hasMVEIntegerOps())
19174 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19175 Ty == MVT::v2i1)) {
19183 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19199 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19200 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19201 Ty == MVT::v2f64) {
19212 const AttributeList &FuncAttributes)
const {
19214 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19215 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19217 if (
Op.size() >= 16 &&
19223 }
else if (
Op.size() >= 8 &&
19240 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19242 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19244 return (SrcBits == 64 && DestBits == 32);
19253 return (SrcBits == 64 && DestBits == 32);
19289 return Subtarget->hasFullFP16();
19296 if (!Subtarget->hasMVEIntegerOps())
19315 if (Ld->isExpandingLoad())
19319 if (Subtarget->hasMVEIntegerOps())
19364bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19366 if (Subtarget->useSoftFloat())
19375 return Subtarget->hasMVEFloatOps();
19393 unsigned Scale = 1;
19410 if ((V & (Scale - 1)) != 0)
19419 if (VT.
isVector() && Subtarget->hasNEON())
19422 !Subtarget->hasMVEFloatOps())
19425 bool IsNeg =
false;
19431 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19434 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19450 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19456 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19486 default:
return false;
19505 int Scale = AM.
Scale;
19510 default:
return false;
19518 Scale = Scale & ~1;
19519 return Scale == 2 || Scale == 4 || Scale == 8;
19536 if (Scale & 1)
return false;
19543 const int Scale = AM.
Scale;
19553 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19569 switch (AM.
Scale) {
19580 if (Subtarget->isThumb1Only())
19583 if (Subtarget->isThumb2())
19586 int Scale = AM.
Scale;
19588 default:
return false;
19592 if (Scale < 0) Scale = -Scale;
19600 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19613 if (Scale & 1)
return false;
19626 if (!Subtarget->isThumb())
19629 if (Subtarget->isThumb2())
19633 return Imm >= 0 && Imm <= 255;
19643 if (!Subtarget->isThumb())
19645 if (Subtarget->isThumb2())
19648 return AbsImm <= 255;
19683 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19687 int RHSC = (int)
RHS->getZExtValue();
19688 if (RHSC < 0 && RHSC > -256) {
19698 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19701 int RHSC = (int)
RHS->getZExtValue();
19702 if (RHSC < 0 && RHSC > -0x1000) {
19744 int RHSC = (int)
RHS->getZExtValue();
19745 if (RHSC < 0 && RHSC > -0x100) {
19750 }
else if (RHSC > 0 && RHSC < 0x100) {
19761 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19772 bool CanChangeType = isLE && !IsMasked;
19775 int RHSC = (int)
RHS->getZExtValue();
19777 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19778 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19783 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19794 if (VT == MVT::v4i16) {
19795 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19797 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19798 if (IsInRange(RHSC, 0x80, 1))
19800 }
else if (Alignment >= 4 &&
19801 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19802 IsInRange(RHSC, 0x80, 4))
19804 else if (Alignment >= 2 &&
19805 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19806 IsInRange(RHSC, 0x80, 2))
19808 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19821 if (Subtarget->isThumb1Only())
19827 bool isSEXTLoad =
false;
19828 bool IsMasked =
false;
19830 Ptr = LD->getBasePtr();
19831 VT = LD->getMemoryVT();
19832 Alignment = LD->getAlign();
19835 Ptr = ST->getBasePtr();
19836 VT = ST->getMemoryVT();
19837 Alignment = ST->getAlign();
19839 Ptr = LD->getBasePtr();
19840 VT = LD->getMemoryVT();
19841 Alignment = LD->getAlign();
19845 Ptr = ST->getBasePtr();
19846 VT = ST->getMemoryVT();
19847 Alignment = ST->getAlign();
19853 bool isLegal =
false;
19855 isLegal = Subtarget->hasMVEIntegerOps() &&
19857 Ptr.getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19858 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19860 if (Subtarget->isThumb2())
19885 bool isSEXTLoad =
false, isNonExt;
19886 bool IsMasked =
false;
19888 VT = LD->getMemoryVT();
19889 Ptr = LD->getBasePtr();
19890 Alignment = LD->getAlign();
19894 VT = ST->getMemoryVT();
19895 Ptr = ST->getBasePtr();
19896 Alignment = ST->getAlign();
19897 isNonExt = !ST->isTruncatingStore();
19899 VT = LD->getMemoryVT();
19900 Ptr = LD->getBasePtr();
19901 Alignment = LD->getAlign();
19906 VT = ST->getMemoryVT();
19907 Ptr = ST->getBasePtr();
19908 Alignment = ST->getAlign();
19909 isNonExt = !ST->isTruncatingStore();
19914 if (Subtarget->isThumb1Only()) {
19917 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19918 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19921 if (!RHS || RHS->getZExtValue() != 4)
19923 if (Alignment <
Align(4))
19927 Base =
Op->getOperand(0);
19933 bool isLegal =
false;
19935 isLegal = Subtarget->hasMVEIntegerOps() &&
19940 if (Subtarget->isThumb2())
19954 !Subtarget->isThumb2())
19968 const APInt &DemandedElts,
19970 unsigned Depth)
const {
19973 switch (
Op.getOpcode()) {
19980 if (
Op.getResNo() == 0) {
20006 case Intrinsic::arm_ldaex:
20007 case Intrinsic::arm_ldrex: {
20022 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20023 Known.
Zero &= Mask;
20029 const SDValue &SrcSV =
Op.getOperand(0);
20035 "VGETLANE index out of bounds");
20040 EVT VT =
Op.getValueType();
20047 Known = Known.
sext(DstSz);
20049 Known = Known.
zext(DstSz);
20057 Known = KnownOp.
zext(32);
20084 unsigned Encoded =
Op.getConstantOperandVal(1);
20085 unsigned DecEltBits = 0;
20088 unsigned EltBits =
Op.getScalarValueSizeInBits();
20089 if (EltBits != DecEltBits) {
20099 APInt Imm(DecEltBits, DecodedVal);
20101 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20102 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20120 EVT VT =
Op.getValueType();
20126 assert(VT == MVT::i32 &&
"Unexpected integer type");
20133 unsigned Mask =
C->getZExtValue();
20136 unsigned ShrunkMask = Mask & Demanded;
20137 unsigned ExpandedMask = Mask | ~Demanded;
20141 if (ShrunkMask == 0)
20147 if (ExpandedMask == ~0U)
20150 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20151 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20153 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20154 if (NewMask == Mask)
20163 if (IsLegalMask(0xFF))
20164 return UseMask(0xFF);
20167 if (IsLegalMask(0xFFFF))
20168 return UseMask(0xFFFF);
20172 if (ShrunkMask < 256)
20173 return UseMask(ShrunkMask);
20177 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20178 return UseMask(ExpandedMask);
20193 unsigned Depth)
const {
20194 unsigned Opc =
Op.getOpcode();
20202 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20204 unsigned ShAmt =
Op->getConstantOperandVal(2);
20216 unsigned ModImm =
Op.getConstantOperandVal(1);
20217 unsigned EltBits = 0;
20219 if ((OriginalDemandedBits & Mask) == 0)
20225 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20240 if (!Subtarget->hasVFP2Base())
20244 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20256 unsigned S = Constraint.
size();
20258 switch (Constraint[0]) {
20270 }
else if (S == 2) {
20271 switch (Constraint[0]) {
20288 Value *CallOperandVal =
info.CallOperandVal;
20291 if (!CallOperandVal)
20295 switch (*constraint) {
20301 if (Subtarget->isThumb())
20316 if (PR == 0 || VT == MVT::Other)
20318 if (ARM::SPRRegClass.
contains(PR))
20319 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20320 if (ARM::DPRRegClass.
contains(PR))
20325using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20329 switch (Constraint.
size()) {
20332 switch (Constraint[0]) {
20334 if (Subtarget->isThumb())
20335 return RCPair(0U, &ARM::tGPRRegClass);
20336 return RCPair(0U, &ARM::GPRRegClass);
20338 if (Subtarget->isThumb())
20339 return RCPair(0U, &ARM::hGPRRegClass);
20342 if (Subtarget->isThumb1Only())
20343 return RCPair(0U, &ARM::tGPRRegClass);
20344 return RCPair(0U, &ARM::GPRRegClass);
20346 if (VT == MVT::Other)
20348 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20349 return RCPair(0U, &ARM::SPRRegClass);
20351 return RCPair(0U, &ARM::DPRRegClass);
20353 return RCPair(0U, &ARM::QPRRegClass);
20356 if (VT == MVT::Other)
20358 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20359 return RCPair(0U, &ARM::SPR_8RegClass);
20361 return RCPair(0U, &ARM::DPR_8RegClass);
20363 return RCPair(0U, &ARM::QPR_8RegClass);
20366 if (VT == MVT::Other)
20368 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20369 return RCPair(0U, &ARM::SPRRegClass);
20371 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20373 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20379 if (Constraint[0] ==
'T') {
20380 switch (Constraint[1]) {
20384 return RCPair(0U, &ARM::tGPREvenRegClass);
20386 return RCPair(0U, &ARM::tGPROddRegClass);
20395 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20396 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20400 return {0,
nullptr};
20408 std::vector<SDValue> &
Ops,
20413 if (Constraint.
size() != 1)
20416 char ConstraintLetter = Constraint[0];
20417 switch (ConstraintLetter) {
20420 case 'I':
case 'J':
case 'K':
case 'L':
20421 case 'M':
case 'N':
case 'O':
20426 int64_t CVal64 =
C->getSExtValue();
20427 int CVal = (int) CVal64;
20430 if (CVal != CVal64)
20433 switch (ConstraintLetter) {
20437 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20438 if (CVal >= 0 && CVal <= 65535)
20442 if (Subtarget->isThumb1Only()) {
20445 if (CVal >= 0 && CVal <= 255)
20447 }
else if (Subtarget->isThumb2()) {
20461 if (Subtarget->isThumb1Only()) {
20466 if (CVal >= -255 && CVal <= -1)
20472 if (CVal >= -4095 && CVal <= 4095)
20478 if (Subtarget->isThumb1Only()) {
20485 }
else if (Subtarget->isThumb2()) {
20505 if (Subtarget->isThumb1Only()) {
20508 if (CVal >= -7 && CVal < 7)
20510 }
else if (Subtarget->isThumb2()) {
20530 if (Subtarget->isThumb1Only()) {
20533 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20539 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20545 if (Subtarget->isThumb1Only()) {
20547 if (CVal >= 0 && CVal <= 31)
20553 if (Subtarget->isThumb1Only()) {
20556 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20565 if (Result.getNode()) {
20566 Ops.push_back(Result);
20576 "Unhandled Opcode in getDivRemLibcall");
20582 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20583 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20584 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20585 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20594 "Unhandled Opcode in getDivRemArgList");
20598 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20599 EVT ArgVT =
N->getOperand(i).getValueType();
20604 Args.push_back(Entry);
20612 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20613 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20614 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20615 "Register-based DivRem lowering only");
20616 unsigned Opcode =
Op->getOpcode();
20618 "Invalid opcode for Div/Rem lowering");
20620 EVT VT =
Op->getValueType(0);
20642 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20643 : Subtarget->hasDivideInARMMode();
20644 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20645 Op->getSimpleValueType(0) == MVT::i32) {
20647 const SDValue Dividend =
Op->getOperand(0);
20648 const SDValue Divisor =
Op->getOperand(1);
20649 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20653 SDValue Values[2] = {Div, Rem};
20670 if (Subtarget->isTargetWindows())
20673 TargetLowering::CallLoweringInfo CLI(DAG);
20678 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20679 return CallInfo.first;
20685 EVT VT =
N->getValueType(0);
20691 Result[0], Result[1]);
20695 std::vector<Type*> RetTyParams;
20696 Type *RetTyElement;
20706 RetTyParams.push_back(RetTyElement);
20707 RetTyParams.push_back(RetTyElement);
20720 if (Subtarget->isTargetWindows())
20728 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20731 SDNode *ResNode = CallResult.first.getNode();
20738 assert(Subtarget->isTargetWindows() &&
"unsupported target platform");
20746 "no-stack-arg-probe")) {
20750 Chain =
SP.getValue(1);
20767 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20778 bool IsStrict =
Op->isStrictFPOpcode();
20779 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20780 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20782 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20783 "Unexpected type for custom-lowering FP_EXTEND");
20785 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20786 "With both FP DP and 16, any FP conversion is legal!");
20788 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20789 "With FP16, 16 to 32 conversion is legal!");
20792 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20797 Loc,
Op.getValueType(), SrcVal);
20812 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20813 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20814 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20815 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20819 {DstVT, MVT::Other}, {Chain, SrcVal});
20822 SrcVal = DAG.
getNode(ISD::FP_EXTEND, Loc, DstVT, SrcVal);
20826 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20827 "Unexpected type for custom-lowering FP_EXTEND");
20828 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20833 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20837 bool IsStrict =
Op->isStrictFPOpcode();
20839 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20841 EVT DstVT =
Op.getValueType();
20842 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20845 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20846 "Unexpected type for custom-lowering FP_ROUND");
20848 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20849 "With both FP DP and 16, any FP conversion is legal!");
20854 if (SrcSz == 32 && Subtarget->hasFP16())
20859 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20860 "Unexpected type for custom-lowering FP_ROUND");
20864 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20876 if (v == 0xffffffff)
20888 bool ForCodeSize)
const {
20889 if (!Subtarget->hasVFP3Base())
20891 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20893 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20896 if (VT == MVT::f32)
20898 if (VT == MVT::f64 && Subtarget->hasFP64())
20911 case Intrinsic::arm_neon_vld1:
20912 case Intrinsic::arm_neon_vld2:
20913 case Intrinsic::arm_neon_vld3:
20914 case Intrinsic::arm_neon_vld4:
20915 case Intrinsic::arm_neon_vld2lane:
20916 case Intrinsic::arm_neon_vld3lane:
20917 case Intrinsic::arm_neon_vld4lane:
20918 case Intrinsic::arm_neon_vld2dup:
20919 case Intrinsic::arm_neon_vld3dup:
20920 case Intrinsic::arm_neon_vld4dup: {
20923 auto &
DL =
I.getDataLayout();
20924 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20926 Info.ptrVal =
I.getArgOperand(0);
20928 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20934 case Intrinsic::arm_neon_vld1x2:
20935 case Intrinsic::arm_neon_vld1x3:
20936 case Intrinsic::arm_neon_vld1x4: {
20939 auto &
DL =
I.getDataLayout();
20940 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20942 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20944 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20949 case Intrinsic::arm_neon_vst1:
20950 case Intrinsic::arm_neon_vst2:
20951 case Intrinsic::arm_neon_vst3:
20952 case Intrinsic::arm_neon_vst4:
20953 case Intrinsic::arm_neon_vst2lane:
20954 case Intrinsic::arm_neon_vst3lane:
20955 case Intrinsic::arm_neon_vst4lane: {
20958 auto &
DL =
I.getDataLayout();
20959 unsigned NumElts = 0;
20960 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20961 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20964 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20967 Info.ptrVal =
I.getArgOperand(0);
20969 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20975 case Intrinsic::arm_neon_vst1x2:
20976 case Intrinsic::arm_neon_vst1x3:
20977 case Intrinsic::arm_neon_vst1x4: {
20980 auto &
DL =
I.getDataLayout();
20981 unsigned NumElts = 0;
20982 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20983 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20986 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20989 Info.ptrVal =
I.getArgOperand(0);
20991 Info.align =
I.getParamAlign(0).valueOrOne();
20996 case Intrinsic::arm_mve_vld2q:
20997 case Intrinsic::arm_mve_vld4q: {
21001 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21003 Info.ptrVal =
I.getArgOperand(0);
21010 case Intrinsic::arm_mve_vst2q:
21011 case Intrinsic::arm_mve_vst4q: {
21014 Type *VecTy =
I.getArgOperand(1)->getType();
21015 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21017 Info.ptrVal =
I.getArgOperand(0);
21024 case Intrinsic::arm_mve_vldr_gather_base:
21025 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21027 Info.ptrVal =
nullptr;
21029 Info.align =
Align(1);
21033 case Intrinsic::arm_mve_vldr_gather_base_wb:
21034 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21036 Info.ptrVal =
nullptr;
21037 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21038 Info.align =
Align(1);
21042 case Intrinsic::arm_mve_vldr_gather_offset:
21043 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21045 Info.ptrVal =
nullptr;
21050 Info.align =
Align(1);
21054 case Intrinsic::arm_mve_vstr_scatter_base:
21055 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21057 Info.ptrVal =
nullptr;
21058 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21059 Info.align =
Align(1);
21063 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21064 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21066 Info.ptrVal =
nullptr;
21067 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21068 Info.align =
Align(1);
21072 case Intrinsic::arm_mve_vstr_scatter_offset:
21073 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21075 Info.ptrVal =
nullptr;
21080 Info.align =
Align(1);
21084 case Intrinsic::arm_ldaex:
21085 case Intrinsic::arm_ldrex: {
21086 auto &
DL =
I.getDataLayout();
21087 Type *ValTy =
I.getParamElementType(0);
21090 Info.ptrVal =
I.getArgOperand(0);
21092 Info.align =
DL.getABITypeAlign(ValTy);
21096 case Intrinsic::arm_stlex:
21097 case Intrinsic::arm_strex: {
21098 auto &
DL =
I.getDataLayout();
21099 Type *ValTy =
I.getParamElementType(1);
21102 Info.ptrVal =
I.getArgOperand(1);
21104 Info.align =
DL.getABITypeAlign(ValTy);
21108 case Intrinsic::arm_stlexd:
21109 case Intrinsic::arm_strexd:
21111 Info.memVT = MVT::i64;
21112 Info.ptrVal =
I.getArgOperand(2);
21114 Info.align =
Align(8);
21118 case Intrinsic::arm_ldaexd:
21119 case Intrinsic::arm_ldrexd:
21121 Info.memVT = MVT::i64;
21122 Info.ptrVal =
I.getArgOperand(0);
21124 Info.align =
Align(8);
21139 assert(Ty->isIntegerTy());
21141 unsigned Bits = Ty->getPrimitiveSizeInBits();
21142 if (Bits == 0 || Bits > 32)
21148 unsigned Index)
const {
21158 if (!Subtarget->hasDataBarrier()) {
21162 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21163 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21164 Builder.getInt32(0), Builder.getInt32(7),
21165 Builder.getInt32(10), Builder.getInt32(5)};
21166 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
21176 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
21197 if (Subtarget->preferISHSTBarriers())
21230 bool has64BitAtomicStore;
21231 if (Subtarget->isMClass())
21232 has64BitAtomicStore =
false;
21233 else if (Subtarget->isThumb())
21234 has64BitAtomicStore = Subtarget->hasV7Ops();
21236 has64BitAtomicStore = Subtarget->hasV6Ops();
21238 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21252 bool has64BitAtomicLoad;
21253 if (Subtarget->isMClass())
21254 has64BitAtomicLoad =
false;
21255 else if (Subtarget->isThumb())
21256 has64BitAtomicLoad = Subtarget->hasV7Ops();
21258 has64BitAtomicLoad = Subtarget->hasV6Ops();
21274 if (Subtarget->isMClass())
21275 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21276 else if (Subtarget->isThumb())
21277 hasAtomicRMW = Subtarget->hasV7Ops();
21279 hasAtomicRMW = Subtarget->hasV6Ops();
21280 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21303 bool HasAtomicCmpXchg;
21304 if (Subtarget->isMClass())
21305 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21306 else if (Subtarget->isThumb())
21307 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21309 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21311 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21318 return InsertFencesForAtomic;
21323 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21328 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21331 RTLIB::LibcallImpl SecurityCookieVar =
21333 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21334 SecurityCookieVar != RTLIB::Unsupported) {
21345 F->addParamAttr(0, Attribute::AttrKind::InReg);
21352 unsigned &
Cost)
const {
21354 if (!Subtarget->hasNEON())
21383 unsigned Opcode =
Op.getOpcode();
21394 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21398 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21403 if (!Subtarget->hasV7Ops())
21409 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21411 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21419 if (Subtarget->hasMinSize() && !Subtarget->isTargetWindows())
21428 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21434 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21436 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21439 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21441 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21442 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21443 if (!Subtarget->isLittle())
21445 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21446 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21447 return Builder.CreateOr(
21448 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21452 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21453 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21456 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21457 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21462 if (!Subtarget->hasV7Ops())
21464 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21470 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21478 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21482 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21483 if (!Subtarget->isLittle())
21485 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21488 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21492 CallInst *CI = Builder.CreateCall(
21493 Strex, {Builder.CreateZExtOrBitCast(
21503 return Subtarget->isMClass();
21511 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21518 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21521 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21529 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21537 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21540 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21545 if (Subtarget->hasNEON() && VecSize == 64)
21547 return VecSize % 128 == 0;
21551 if (Subtarget->hasNEON())
21553 if (Subtarget->hasMVEIntegerOps())
21573 "Invalid interleave factor");
21574 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21576 "Unmatched number of shufflevectors and indices");
21581 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21584 Type *EltTy = VecTy->getElementType();
21587 Align Alignment = LI->getAlign();
21605 Value *BaseAddr = LI->getPointerOperand();
21607 if (NumLoads > 1) {
21611 VecTy->getNumElements() / NumLoads);
21617 if (Subtarget->hasNEON()) {
21618 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21619 Type *Tys[] = {VecTy, PtrTy};
21620 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21621 Intrinsic::arm_neon_vld3,
21622 Intrinsic::arm_neon_vld4};
21625 Ops.push_back(BaseAddr);
21626 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21628 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21631 assert((Factor == 2 || Factor == 4) &&
21632 "expected interleave factor of 2 or 4 for MVE");
21634 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21635 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21636 Type *Tys[] = {VecTy, PtrTy};
21639 Ops.push_back(BaseAddr);
21640 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21650 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21654 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21655 VecTy->getNumElements() * Factor);
21661 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21663 unsigned Index = Indices[i];
21665 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21669 SubVec = Builder.CreateIntToPtr(
21673 SubVecs[SV].push_back(SubVec);
21682 auto &SubVec = SubVecs[SVI];
21685 SVI->replaceAllUsesWith(WideVec);
21721 const APInt &GapMask)
const {
21723 "Invalid interleave factor");
21728 "Unexpected mask on store");
21731 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21733 unsigned LaneLen = VecTy->getNumElements() / Factor;
21734 Type *EltTy = VecTy->getElementType();
21738 Align Alignment =
SI->getAlign();
21755 Type *IntTy =
DL.getIntPtrType(EltTy);
21760 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21761 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21767 Value *BaseAddr =
SI->getPointerOperand();
21769 if (NumStores > 1) {
21772 LaneLen /= NumStores;
21782 if (Subtarget->hasNEON()) {
21783 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21784 Intrinsic::arm_neon_vst3,
21785 Intrinsic::arm_neon_vst4};
21786 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21787 Type *Tys[] = {PtrTy, SubVecTy};
21790 Ops.push_back(BaseAddr);
21792 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21793 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21795 assert((Factor == 2 || Factor == 4) &&
21796 "expected interleave factor of 2 or 4 for MVE");
21798 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21799 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21800 Type *Tys[] = {PtrTy, SubVecTy};
21803 Ops.push_back(BaseAddr);
21805 for (
unsigned F = 0;
F < Factor;
F++) {
21806 Ops.push_back(Builder.getInt32(
F));
21807 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21813 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21816 if (StoreCount > 0)
21817 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21818 BaseAddr, LaneLen * Factor);
21823 for (
unsigned i = 0; i < Factor; i++) {
21824 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21825 if (Mask[IdxI] >= 0) {
21826 Shuffles.
push_back(Builder.CreateShuffleVector(
21829 unsigned StartMask = 0;
21830 for (
unsigned j = 1; j < LaneLen; j++) {
21831 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21832 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21833 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21843 Shuffles.
push_back(Builder.CreateShuffleVector(
21864 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21868 Members += SubMembers;
21874 Members += SubMembers * AT->getNumElements();
21875 }
else if (Ty->isFloatTy()) {
21880 }
else if (Ty->isDoubleTy()) {
21892 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21894 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21896 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21909 return (Members > 0 && Members <= 4);
21915 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21917 return ABITypeAlign;
21922 assert(StackAlign &&
"data layout string is missing stack alignment");
21923 return std::min(ABITypeAlign, *StackAlign);
21932 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21941 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
21942 return IsHA || IsIntArray;
21946 const Constant *PersonalityFn)
const {
21954 const Constant *PersonalityFn)
const {
21967void ARMTargetLowering::insertCopiesSplitCSR(
21971 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21981 RC = &ARM::GPRRegClass;
21982 else if (ARM::DPRRegClass.
contains(*
I))
21983 RC = &ARM::DPRRegClass;
21993 assert(Entry->getParent()->getFunction().hasFnAttribute(
21994 Attribute::NoUnwind) &&
21995 "Function should be nounwind in insertCopiesSplitCSR!");
21996 Entry->addLiveIn(*
I);
22001 for (
auto *Exit : Exits)
22003 TII->get(TargetOpcode::COPY), *
I)
22014 return Subtarget->hasMVEIntegerOps();
22024 unsigned NumElements = VTy->getNumElements();
22031 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22032 return Subtarget->hasMVEFloatOps();
22037 return Subtarget->hasMVEIntegerOps() &&
22038 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22039 ScalarTy->isIntegerTy(32));
22043 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22054 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22056 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22058 if (TyWidth > 128) {
22059 int Stride = Ty->getNumElements() / 2;
22063 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22065 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22066 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22067 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22068 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22069 Value *LowerSplitAcc =
nullptr;
22070 Value *UpperSplitAcc =
nullptr;
22073 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22074 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22078 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22080 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22082 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22083 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22090 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22093 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22095 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22096 {ConstRotation, InputB, InputA});
22101 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22104 ConstRotation = ConstantInt::get(IntTy, 0);
22106 ConstRotation = ConstantInt::get(IntTy, 1);
22108 if (!ConstRotation)
22111 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22112 {ConstHalving, ConstRotation, InputA, InputB});
unsigned const MachineRegisterInfo * MRI
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool isNegatedInteger(SDValue Op)
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue LowerUADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue ConvertBooleanCarryToCarryFlag(SDValue BoolCarry, SelectionDAG &DAG)
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue ConvertCarryFlagToBooleanCarry(SDValue Flags, EVT VT, SelectionDAG &DAG)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static unsigned SelectPairHalf(unsigned Elements, ArrayRef< int > Mask, unsigned Index)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerTruncate(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformHWLoopCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, Value *Offset, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, Value *Offset, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned int Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static constexpr roundingMode rmTowardZero
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 isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void insertSSPDeclarations(Module &M) const override
Inserts necessary declarations for SSP (stack protection) purpose.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
bool shouldFoldConstantShiftPairToMask(const SDNode *N) const override
Return true if it is profitable to fold a pair of shifts into a mask.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override
Return true if it is profitable to combine an XOR of a logical shift to create a logical shift of NOT...
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const
PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
Value * createComplexDeinterleavingIR(IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, Value *Accumulator=nullptr) const override
Create the IR node for the given complex deinterleaving operation.
bool isComplexDeinterleavingSupported() const override
Does this target support complex deinterleaving.
SDValue PerformMVEExtCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &OriginalDemandedBits, const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the value type to use for ISD::SETCC.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const override
Perform a store-conditional operation to Addr.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool isVarArg) const
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for this result type with this index.
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
isShuffleMaskLegal - Targets can use this to indicate that they only support some VECTOR_SHUFFLE oper...
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
bool lowerInterleavedStore(Instruction *Store, Value *Mask, ShuffleVectorInst *SVI, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved store into a vstN intrinsic.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
bool useLoadStackGuardNode(const Module &M) const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vldN intrinsic.
std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override
Return the largest legal super-reg register class of the register class for the specified type and it...
bool preferSelectsOverBooleanArithmetic(EVT VT) const override
Should we prefer selects to doing arithmetic on boolean types.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
bool supportKCFIBundles() const override
Return true if the target supports kcfi operand bundles.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
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
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
MaybeAlign getStackAlignment() const
Returns the natural stack alignment, or MaybeAlign() if one wasn't specified.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
StringRef getPrivateGlobalPrefix() const
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Describe properties that are true of each instruction in the target description file.
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
bool is64BitVector() const
Return true if this is a 64-bit vector type.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI unsigned createJumpTableIndex(const std::vector< MachineBasicBlock * > &DestBBs)
createJumpTableIndex - Create a new jump table.
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
This class is used to represent an MLOAD node.
This class is used to represent an MSTORE node.
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
This instruction constructs a fixed permutation of two input vectors.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
StringRef - Represent a constant reference to a string, i.e.
const unsigned char * bytes_end() const
constexpr size_t size() const
size - Get the string size.
const unsigned char * bytes_begin() const
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
Provides information about what library functions are available for the current target.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const
Get the CallingConv that should be used for the specified libcall.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
ShiftLegalizationStrategy
Return the preferred strategy to legalize tihs SHIFT instruction, with ExpansionFactor being the recu...
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
const TargetMachine & getTargetMachine() const
void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked load does or does not work with the specified type and ind...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked store does or does not work with the specified type and in...
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
static StringRef getLibcallImplName(RTLIB::LibcallImpl Call)
Get the libcall routine name for the specified libcall implementation.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl)
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
virtual void insertSSPDeclarations(Module &M) const
Inserts necessary declarations for SSP (stack protection) purpose.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool expandDIVREMByConstant(SDNode *N, SmallVectorImpl< SDValue > &Result, EVT HiLoVT, SelectionDAG &DAG, SDValue LL=SDValue(), SDValue LH=SDValue()) const
Attempt to expand an n-bit div/rem/divrem by constant using a n/2-bit urem by constant and other arit...
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual ArrayRef< MCPhysReg > getRoundingControlRegisters() const
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
ExceptionHandling getExceptionModel() const
Return the ExceptionHandling to use, considering TargetOptions and the Triple's default.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
unsigned EmitCallGraphSection
Emit section containing call graph metadata.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
Base class of all SIMD vector types.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static CondCodes getOppositeCondition(CondCodes CC)
@ SECREL
Thread Pointer Offset.
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
TOF
Target Operand Flag enum.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2Offset(unsigned AM2Opc)
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
AddrOpc getAM2Op(unsigned AM2Opc)
bool isBitFieldInvertedMask(unsigned v)
const unsigned FPStatusBits
const unsigned FPReservedBits
const unsigned RoundingBitsPos
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Swift
Calling convention for Swift.
@ ARM_APCS
ARM Procedure Calling Standard (obsolete, but still used on some targets).
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ ARM_AAPCS
ARM Architecture Procedure Calling Standard calling convention (aka EABI).
@ CXX_FAST_TLS
Used for access functions.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ ARM_AAPCS_VFP
Same as ARM_AAPCS, but uses hard floating point ABI.
@ C
The default llvm calling convention, compatible with C.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
@ FGETSIGN
INT = FGETSIGN(FP) - Return the sign bit of the specified floating point value as an integer 0/1 valu...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ EH_SJLJ_SETUP_DISPATCH
OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) The target initializes the dispatch table here.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ SSUBO
Same for subtraction.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ SMULO
Same for multiplication.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ SjLj
setjmp/longjmp based exceptions
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
FunctionAddr VTableAddr uintptr_t uintptr_t Data
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
bool isUnknown() const
Returns true if we don't know any bits.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)