84#include "llvm/IR/IntrinsicsARM.h"
119#define DEBUG_TYPE "arm-isel"
122STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
123STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
125 "Number of constants with their storage promoted into constant pools");
129 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
134 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
139 cl::desc(
"Maximum size of constant to promote into a constant pool"),
143 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
148 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
153 cl::desc(
"Maximum number of base-updates to check generating postindex."),
161 ARM::R0, ARM::R1, ARM::R2, ARM::R3
175void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
176 if (VT != PromotedLdStVT) {
185 if (ElemTy != MVT::f64)
189 if (ElemTy == MVT::i32) {
233void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
235 addTypeForNEON(VT, MVT::f64);
238void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
240 addTypeForNEON(VT, MVT::v2f64);
243void ARMTargetLowering::setAllExpand(
MVT VT) {
256void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
263void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
264 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
266 for (
auto VT : IntTypes) {
340 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
341 for (
auto VT : FloatTypes) {
415 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
416 for (
auto VT : LongTypes) {
433 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
434 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
435 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
452 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
461 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
462 for (
auto VT : pTypes) {
513 RegInfo(Subtarget->getRegisterInfo()),
514 Itins(Subtarget->getInstrItineraryData()) {
520 const Triple &TT = TM.getTargetTriple();
522 if (TT.isOSBinFormatMachO()) {
524 if (Subtarget->isThumb() && Subtarget->hasVFP2Base() &&
525 Subtarget->hasARMOps() && !Subtarget->useSoftFloat()) {
527 static const struct {
528 const RTLIB::Libcall
Op;
529 const RTLIB::LibcallImpl Impl;
532 { RTLIB::ADD_F32, RTLIB::impl___addsf3vfp },
533 { RTLIB::SUB_F32, RTLIB::impl___subsf3vfp },
534 { RTLIB::MUL_F32, RTLIB::impl___mulsf3vfp },
535 { RTLIB::DIV_F32, RTLIB::impl___divsf3vfp },
538 { RTLIB::ADD_F64, RTLIB::impl___adddf3vfp },
539 { RTLIB::SUB_F64, RTLIB::impl___subdf3vfp },
540 { RTLIB::MUL_F64, RTLIB::impl___muldf3vfp },
541 { RTLIB::DIV_F64, RTLIB::impl___divdf3vfp },
544 { RTLIB::OEQ_F32, RTLIB::impl___eqsf2vfp },
545 { RTLIB::UNE_F32, RTLIB::impl___nesf2vfp },
546 { RTLIB::OLT_F32, RTLIB::impl___ltsf2vfp },
547 { RTLIB::OLE_F32, RTLIB::impl___lesf2vfp },
548 { RTLIB::OGE_F32, RTLIB::impl___gesf2vfp },
549 { RTLIB::OGT_F32, RTLIB::impl___gtsf2vfp },
550 { RTLIB::UO_F32, RTLIB::impl___unordsf2vfp },
553 { RTLIB::OEQ_F64, RTLIB::impl___eqdf2vfp },
554 { RTLIB::UNE_F64, RTLIB::impl___nedf2vfp },
555 { RTLIB::OLT_F64, RTLIB::impl___ltdf2vfp },
556 { RTLIB::OLE_F64, RTLIB::impl___ledf2vfp },
557 { RTLIB::OGE_F64, RTLIB::impl___gedf2vfp },
558 { RTLIB::OGT_F64, RTLIB::impl___gtdf2vfp },
559 { RTLIB::UO_F64, RTLIB::impl___unorddf2vfp },
564 { RTLIB::FPTOSINT_F64_I32, RTLIB::impl___fixdfsivfp },
565 { RTLIB::FPTOUINT_F64_I32, RTLIB::impl___fixunsdfsivfp },
566 { RTLIB::FPTOSINT_F32_I32, RTLIB::impl___fixsfsivfp },
567 { RTLIB::FPTOUINT_F32_I32, RTLIB::impl___fixunssfsivfp },
570 { RTLIB::FPROUND_F64_F32, RTLIB::impl___truncdfsf2vfp },
571 { RTLIB::FPEXT_F32_F64, RTLIB::impl___extendsfdf2vfp },
578 { RTLIB::SINTTOFP_I32_F64, RTLIB::impl___floatsidfvfp },
579 { RTLIB::UINTTOFP_I32_F64, RTLIB::impl___floatunssidfvfp },
580 { RTLIB::SINTTOFP_I32_F32, RTLIB::impl___floatsisfvfp },
581 { RTLIB::UINTTOFP_I32_F32, RTLIB::impl___floatunssisfvfp },
585 for (
const auto &LC : LibraryCalls)
590 if (Subtarget->isThumb1Only())
595 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
596 Subtarget->hasFPRegs()) {
605 if (!Subtarget->hasVFP2Base())
606 setAllExpand(MVT::f32);
607 if (!Subtarget->hasFP64())
608 setAllExpand(MVT::f64);
611 if (Subtarget->hasFullFP16()) {
620 if (Subtarget->hasBF16()) {
622 setAllExpand(MVT::bf16);
623 if (!Subtarget->hasFullFP16())
635 addAllExtLoads(VT, InnerVT,
Expand);
644 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
647 if (!Subtarget->hasV8_1MMainlineOps())
650 if (!Subtarget->isThumb1Only())
659 if (Subtarget->hasMVEIntegerOps())
660 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
663 if (Subtarget->hasLOB()) {
667 if (Subtarget->hasNEON()) {
668 addDRTypeForNEON(MVT::v2f32);
669 addDRTypeForNEON(MVT::v8i8);
670 addDRTypeForNEON(MVT::v4i16);
671 addDRTypeForNEON(MVT::v2i32);
672 addDRTypeForNEON(MVT::v1i64);
674 addQRTypeForNEON(MVT::v4f32);
675 addQRTypeForNEON(MVT::v2f64);
676 addQRTypeForNEON(MVT::v16i8);
677 addQRTypeForNEON(MVT::v8i16);
678 addQRTypeForNEON(MVT::v4i32);
679 addQRTypeForNEON(MVT::v2i64);
681 if (Subtarget->hasFullFP16()) {
682 addQRTypeForNEON(MVT::v8f16);
683 addDRTypeForNEON(MVT::v4f16);
686 if (Subtarget->hasBF16()) {
687 addQRTypeForNEON(MVT::v8bf16);
688 addDRTypeForNEON(MVT::v4bf16);
692 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
732 if (Subtarget->hasNEON()) {
773 ISD::FRINT, ISD::FTRUNC, ISD::FROUNDEVEN}) {
845 if (!Subtarget->hasVFP4Base()) {
854 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
863 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
872 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
880 if (Subtarget->hasMVEIntegerOps()) {
885 if (Subtarget->hasMVEFloatOps()) {
889 if (!Subtarget->hasFP64()) {
934 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
937 if (Subtarget->hasFullFP16()) {
943 if (!Subtarget->hasFP16()) {
969 if (!Subtarget->isThumb1Only()) {
994 if (Subtarget->hasDSP()) {
1004 if (Subtarget->hasBaseDSP()) {
1012 if (Subtarget->isThumb1Only()) {
1016 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
1017 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1032 if (Subtarget->hasMVEIntegerOps())
1036 if (Subtarget->isThumb1Only()) {
1042 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1056 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1065 if (Subtarget->hasPerfMon())
1069 if (!Subtarget->hasV6Ops())
1072 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1073 : Subtarget->hasDivideInARMMode();
1080 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1092 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1093 TT.isTargetMuslAEABI() || TT.isOSWindows()) {
1096 HasStandaloneRem =
false;
1123 if (TT.isOSWindows())
1130 InsertFencesForAtomic =
false;
1131 if (Subtarget->hasAnyDataBarrier() &&
1132 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1136 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1141 if (!Subtarget->hasAcquireRelease() ||
1144 InsertFencesForAtomic =
true;
1150 if (Subtarget->hasDataBarrier())
1151 InsertFencesForAtomic =
true;
1171 if (!InsertFencesForAtomic) {
1178 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1190 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1191 Subtarget->hasForced32BitAtomics()) {
1205 if (!Subtarget->hasV6Ops()) {
1211 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1212 !Subtarget->isThumb1Only()) {
1241 if (Subtarget->hasFullFP16()) {
1251 if (Subtarget->hasFullFP16())
1266 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1267 !Subtarget->isThumb1Only()) {
1274 if (!Subtarget->hasVFP4Base()) {
1280 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1282 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1288 if (!Subtarget->hasFP16()) {
1310 if (Subtarget->hasFPARMv8Base()) {
1320 if (Subtarget->hasNEON()) {
1327 if (Subtarget->hasFP64()) {
1341 if (Subtarget->hasFullFP16()) {
1367 if (Subtarget->hasNEON()) {
1379 if (Subtarget->hasV8Ops()) {
1394 if (Subtarget->hasFullFP16()) {
1422 if (TT.isOSWindows()) {
1439 if (Subtarget->hasMVEIntegerOps())
1442 if (Subtarget->hasV6Ops())
1444 if (Subtarget->isThumb1Only())
1447 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1448 Subtarget->isThumb2()) {
1454 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1455 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1477 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1483 return Subtarget->useSoftFloat();
1487 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1500std::pair<const TargetRegisterClass *, uint8_t>
1511 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1512 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1513 RRC = &ARM::DPRRegClass;
1518 if (Subtarget->useNEONForSinglePrecisionFP())
1521 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1522 case MVT::v4f32:
case MVT::v2f64:
1523 RRC = &ARM::DPRRegClass;
1527 RRC = &ARM::DPRRegClass;
1531 RRC = &ARM::DPRRegClass;
1535 return std::make_pair(RRC,
Cost);
1539#define MAKE_CASE(V) \
1758 if ((Subtarget->hasMVEIntegerOps() &&
1759 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1760 VT == MVT::v16i8)) ||
1761 (Subtarget->hasMVEFloatOps() &&
1762 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1776 if (Subtarget->hasNEON()) {
1777 if (VT == MVT::v4i64)
1778 return &ARM::QQPRRegClass;
1779 if (VT == MVT::v8i64)
1780 return &ARM::QQQQPRRegClass;
1782 if (Subtarget->hasMVEIntegerOps()) {
1783 if (VT == MVT::v4i64)
1784 return &ARM::MQQPRRegClass;
1785 if (VT == MVT::v8i64)
1786 return &ARM::MQQQQPRRegClass;
1795 Align &PrefAlign)
const {
1802 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1814 unsigned NumVals =
N->getNumValues();
1818 for (
unsigned i = 0; i != NumVals; ++i) {
1819 EVT VT =
N->getValueType(i);
1820 if (VT == MVT::Glue || VT == MVT::Other)
1826 if (!
N->isMachineOpcode())
1834 if (
MCID.getNumDefs() == 0)
1836 if (!Itins->isEmpty() &&
1837 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1851 return Const->getZExtValue() == 16;
1859 return Const->getZExtValue() == 16;
1867 return Const->getZExtValue() == 16;
1936 bool isVarArg)
const {
1955 if (!
getTM().isAAPCS_ABI())
1957 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1965 if (!
getTM().isAAPCS_ABI()) {
1966 if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() && !isVarArg)
1969 }
else if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() &&
1978 bool isVarArg)
const {
1979 return CCAssignFnForNode(CC,
false, isVarArg);
1983 bool isVarArg)
const {
1984 return CCAssignFnForNode(CC,
true, isVarArg);
1991 bool isVarArg)
const {
1992 switch (getEffectiveCallingConv(CC, isVarArg)) {
2018 if (Subtarget->hasFullFP16()) {
2023 Val = DAG.
getNode(ISD::BITCAST, dl, ValVT, Val);
2031 if (Subtarget->hasFullFP16()) {
2035 Val = DAG.
getNode(ISD::BITCAST, dl,
2040 return DAG.
getNode(ISD::BITCAST, dl, LocVT, Val);
2045SDValue ARMTargetLowering::LowerCallResult(
2049 SDValue ThisVal,
bool isCmseNSCall)
const {
2057 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
2058 CCValAssign VA = RVLocs[i];
2062 if (i == 0 && isThisReturn) {
2064 "unexpected return calling convention register assignment");
2082 if (!Subtarget->isLittle())
2099 if (!Subtarget->isLittle())
2142std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
2144 bool IsTailCall,
int SPDiff)
const {
2146 MachinePointerInfo DstInfo;
2166 return std::make_pair(DstAddr, DstInfo);
2175ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
2188 if (!SrcFrameIdxNode || !DstFrameIdxNode)
2191 int SrcFI = SrcFrameIdxNode->getIndex();
2192 int DstFI = DstFrameIdxNode->getIndex();
2194 "byval passed in non-fixed stack slot");
2216 if (SrcOffset == DstOffset)
2224 RegsToPassVector &RegsToPass,
2231 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
2232 unsigned id = Subtarget->isLittle() ? 0 : 1;
2244 MachinePointerInfo DstInfo;
2245 std::tie(DstAddr, DstInfo) =
2246 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2263 SelectionDAG &DAG = CLI.
DAG;
2265 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2266 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2267 SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2274 const CallBase *CB = CLI.
CB;
2277 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2279 MachineFunction::CallSiteInfo CSInfo;
2280 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2281 bool isThisReturn =
false;
2282 bool isCmseNSCall =
false;
2283 bool isSibCall =
false;
2284 bool PreferIndirect =
false;
2285 bool GuardWithBTI =
false;
2295 !Subtarget->noBTIAtReturnTwice())
2300 CSInfo = MachineFunction::CallSiteInfo(*CB);
2304 isCmseNSCall =
true;
2307 if (!Subtarget->supportsTailCall())
2323 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2324 count_if(GV->users(), [&BB](
const User *U) {
2325 return isa<Instruction>(U) &&
2326 cast<Instruction>(U)->getParent() == BB;
2333 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2347 "site marked musttail");
2350 unsigned NumBytes = CCInfo.getStackSize();
2359 if (isTailCall && !isSibCall) {
2360 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2361 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2366 assert(StackAlign &&
"data layout string is missing stack alignment");
2367 NumBytes =
alignTo(NumBytes, *StackAlign);
2372 SPDiff = NumReusableBytes - NumBytes;
2376 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2392 RegsToPassVector RegsToPass;
2401 DenseMap<unsigned, SDValue> ByValTemporaries;
2405 for (
const CCValAssign &VA : ArgLocs) {
2407 SDValue Src = OutVals[ArgIdx];
2408 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2410 if (!
Flags.isByVal())
2414 MachinePointerInfo DstInfo;
2415 std::tie(Dst, DstInfo) =
2416 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2417 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2419 if (Copy == NoCopy) {
2424 }
else if (Copy == CopyOnce) {
2428 ByValTemporaries[ArgIdx] = Src;
2430 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2434 int TempFrameIdx = MFI.CreateStackObject(
2435 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2443 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2444 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2447 ByValTemporaries[ArgIdx] = Temp;
2450 if (!ByValCopyChains.
empty())
2460 bool AfterFormalArgLoads =
false;
2464 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2466 ++i, ++realArgIdx) {
2467 CCValAssign &VA = ArgLocs[i];
2468 SDValue Arg = OutVals[realArgIdx];
2469 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2470 bool isByVal =
Flags.isByVal();
2490 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2495 AfterFormalArgLoads =
true;
2507 auto ArgVT = Outs[realArgIdx].ArgVT;
2508 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2526 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2527 StackPtr, MemOpChains, isTailCall, SPDiff);
2531 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2532 StackPtr, MemOpChains, isTailCall, SPDiff);
2536 MachinePointerInfo DstInfo;
2537 std::tie(DstAddr, DstInfo) =
2538 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2542 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2543 StackPtr, MemOpChains, isTailCall, SPDiff);
2545 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2546 Outs[0].VT == MVT::i32) {
2548 "unexpected calling convention register assignment");
2549 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2550 "unexpected use of 'returned'");
2551 isThisReturn =
true;
2556 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2557 }
else if (isByVal) {
2559 unsigned offset = 0;
2563 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2564 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2567 bool NeedsStackCopy;
2568 if (
auto It = ByValTemporaries.
find(realArgIdx);
2569 It != ByValTemporaries.
end()) {
2570 ByValSrc = It->second;
2571 NeedsStackCopy =
true;
2574 NeedsStackCopy = !isTailCall;
2578 if (CurByValIdx < ByValArgsCount) {
2579 unsigned RegBegin, RegEnd;
2580 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2584 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2588 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2591 RegsToPass.push_back(std::make_pair(j, Load));
2596 offset = RegEnd - RegBegin;
2598 CCInfo.nextInRegsParam();
2603 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2606 MachinePointerInfo DstInfo;
2607 std::tie(Dst, DstInfo) =
2608 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2616 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2617 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2624 MachinePointerInfo DstInfo;
2625 std::tie(DstAddr, DstInfo) =
2626 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2633 if (!MemOpChains.
empty())
2639 for (
const auto &[
Reg,
N] : RegsToPass) {
2647 bool isDirect =
false;
2650 const GlobalValue *GVal =
nullptr;
2652 GVal =
G->getGlobal();
2653 bool isStub = !TM.shouldAssumeDSOLocal(GVal) && Subtarget->isTargetMachO();
2655 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2656 bool isLocalARMFunc =
false;
2659 if (Subtarget->genLongCalls()) {
2661 "long-calls codegen is not position independent!");
2666 if (Subtarget->genExecuteOnly()) {
2667 if (Subtarget->useMovt())
2685 const char *Sym = S->getSymbol();
2687 if (Subtarget->genExecuteOnly()) {
2688 if (Subtarget->useMovt())
2707 if (!PreferIndirect) {
2712 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2714 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2715 assert(Subtarget->isTargetMachO() &&
"WrapperPIC use on non-MachO?");
2724 }
else if (Subtarget->isTargetCOFF()) {
2725 assert(Subtarget->isTargetWindows() &&
2726 "Windows is the only supported COFF target");
2730 else if (!TM.shouldAssumeDSOLocal(GVal))
2746 const char *Sym = S->getSymbol();
2747 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2749 ARMConstantPoolValue *CPV =
2751 ARMPCLabelIndex, 4);
2765 assert(!isARMFunc && !isDirect &&
2766 "Cannot handle call to ARM function or direct call");
2770 "call to non-secure function would require "
2771 "passing arguments on stack",
2777 "call to non-secure function would return value through pointer",
2784 if (Subtarget->isThumb()) {
2787 else if (isCmseNSCall)
2789 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2794 if (!isDirect && !Subtarget->hasV5TOps())
2796 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2798 !Subtarget->hasMinSize())
2809 if (isTailCall && !isSibCall) {
2814 std::vector<SDValue>
Ops;
2815 Ops.push_back(Chain);
2816 Ops.push_back(Callee);
2824 for (
const auto &[
Reg,
N] : RegsToPass)
2828 const uint32_t *
Mask;
2829 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2837 isThisReturn =
false;
2843 assert(Mask &&
"Missing call preserved mask for calling convention");
2847 Ops.push_back(InGlue);
2858 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2867 uint64_t CalleePopBytes =
2870 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2876 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2877 InVals, isThisReturn,
2878 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2885void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2886 Align Alignment)
const {
2888 Alignment = std::max(Alignment,
Align(4));
2894 unsigned AlignInRegs = Alignment.
value() / 4;
2895 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2896 for (
unsigned i = 0; i < Waste; ++i)
2902 unsigned Excess = 4 * (ARM::R4 -
Reg);
2909 if (NSAAOffset != 0 &&
Size > Excess) {
2921 unsigned ByValRegBegin =
Reg;
2922 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2926 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2932 Size = std::max<int>(
Size - Excess, 0);
2940bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2946 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2947 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2948 const SmallVectorImpl<ISD::InputArg> &
Ins = CLI.
Ins;
2949 const SelectionDAG &DAG = CLI.
DAG;
2954 assert(Subtarget->supportsTailCall());
2967 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2969 if (!(Subtarget->isThumb1Only() ||
2970 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2971 AddressRegisters.
insert(ARM::R12);
2972 for (
const CCValAssign &AL : ArgLocs)
2974 AddressRegisters.
erase(
AL.getLocReg());
2975 if (AddressRegisters.
empty()) {
2976 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2995 <<
" (guaranteed tail-call CC)\n");
2996 return CalleeCC == CallerCC;
3001 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
3003 if (isCalleeStructRet != isCallerStructRet) {
3016 const GlobalValue *GV =
G->getGlobal();
3019 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
3020 TT.isOSBinFormatMachO())) {
3029 getEffectiveCallingConv(CalleeCC, isVarArg),
3030 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
3037 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3038 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
3039 if (CalleeCC != CallerCC) {
3040 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
3041 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
3050 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
3060 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
3079 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
3088 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
3101 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
3104 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
3108 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
3135 bool isLittleEndian = Subtarget->isLittle();
3138 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3147 "secure entry function would return value through pointer",
3152 for (
unsigned i = 0, realRVLocIdx = 0;
3154 ++i, ++realRVLocIdx) {
3155 CCValAssign &VA = RVLocs[i];
3158 SDValue Arg = OutVals[realRVLocIdx];
3159 bool ReturnF16 =
false;
3161 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
3194 auto RetVT = Outs[realRVLocIdx].ArgVT;
3216 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3220 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3226 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3238 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3240 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3245 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3255 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3281 !Subtarget->isMClass()) {
3282 if (Subtarget->isThumb1Only())
3289 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3292bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3293 if (
N->getNumValues() != 1)
3295 if (!
N->hasNUsesOfValue(1, 0))
3299 SDNode *
Copy = *
N->user_begin();
3303 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3305 TCChain =
Copy->getOperand(0);
3307 SDNode *VMov =
Copy;
3309 SmallPtrSet<SDNode*, 2>
Copies;
3310 for (SDNode *U : VMov->
users()) {
3318 for (SDNode *U : VMov->
users()) {
3319 SDValue UseChain =
U->getOperand(0);
3327 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3333 }
else if (
Copy->getOpcode() == ISD::BITCAST) {
3335 if (!
Copy->hasOneUse())
3342 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3344 TCChain =
Copy->getOperand(0);
3349 bool HasRet =
false;
3350 for (
const SDNode *U :
Copy->users()) {
3364bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3365 if (!Subtarget->supportsTailCall())
3382 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3398 EVT PtrVT =
Op.getValueType();
3408 if (Subtarget->genExecuteOnly()) {
3410 auto *
T =
CP->getType();
3411 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3413 auto GV =
new GlobalVariable(
3421 return LowerGlobalAddress(GA, DAG);
3426 Align CPAlign =
CP->getAlign();
3427 if (Subtarget->isThumb1Only())
3428 CPAlign = std::max(CPAlign,
Align(4));
3429 if (
CP->isMachineConstantPoolEntry())
3441 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3450 unsigned ARMPCLabelIndex = 0;
3456 if (!IsPositionIndependent) {
3459 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3470 if (!IsPositionIndependent)
3501ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3503 assert(Subtarget->isTargetDarwin() &&
3504 "This function expects a Darwin target");
3509 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3515 MVT::i32,
DL, Chain, DescAddr,
3530 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3539 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3545ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3547 assert(Subtarget->isTargetWindows() &&
"Windows specific TLS lowering");
3571 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3580 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3586 MachinePointerInfo());
3606 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3608 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3610 ARMConstantPoolValue *CPV =
3628 TargetLowering::CallLoweringInfo CLI(DAG);
3633 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3634 return CallResult.first;
3643 const GlobalValue *GV = GA->
getGlobal();
3653 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3656 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3657 ARMConstantPoolValue *CPV =
3664 PtrVT, dl, Chain,
Offset,
3672 PtrVT, dl, Chain,
Offset,
3677 ARMConstantPoolValue *CPV =
3682 PtrVT, dl, Chain,
Offset,
3697 if (Subtarget->isTargetDarwin())
3698 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3700 if (Subtarget->isTargetWindows())
3701 return LowerGlobalTLSAddressWindows(
Op, DAG);
3704 assert(Subtarget->isTargetELF() &&
"Only ELF implemented here");
3710 return LowerToTLSGeneralDynamicModel(GA, DAG);
3713 return LowerToTLSExecModels(GA, DAG, model);
3722 while (!Worklist.
empty()) {
3730 if (!
I ||
I->getParent()->getParent() !=
F)
3759 if (!GVar || !GVar->hasInitializer() ||
3760 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3761 !GVar->hasLocalLinkage())
3766 auto *
Init = GVar->getInitializer();
3768 Init->needsDynamicRelocation())
3780 unsigned RequiredPadding = 4 - (
Size % 4);
3781 bool PaddingPossible =
3782 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3787 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3811 if (RequiredPadding != 4) {
3816 while (RequiredPadding--)
3828 ++NumConstpoolPromoted;
3834 if (!(GV = GA->getAliaseeObject()))
3837 return V->isConstant();
3846 return LowerGlobalAddressWindows(
Op, DAG);
3848 return LowerGlobalAddressELF(
Op, DAG);
3850 return LowerGlobalAddressDarwin(
Op, DAG);
3862 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3875 }
else if (Subtarget->isROPI() && IsRO) {
3880 }
else if (Subtarget->isRWPI() && !IsRO) {
3883 if (Subtarget->useMovt()) {
3888 ARMConstantPoolValue *CPV =
3905 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3906 if (Subtarget->useMovt())
3923 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3924 "ROPI/RWPI not currently supported for Darwin");
3929 if (Subtarget->useMovt())
3940 if (Subtarget->isGVIndirectSymbol(GV))
3948 assert(Subtarget->isTargetWindows() &&
"non-Windows COFF is not supported");
3949 assert(Subtarget->useMovt() &&
3950 "Windows on ARM expects to use movw/movt");
3951 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3952 "ROPI/RWPI not currently supported for Windows");
3959 else if (!TM.shouldAssumeDSOLocal(GV))
3983 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3984 Op.getOperand(1), Val);
4001SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
4004 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
4008 case Intrinsic::arm_gnu_eabi_mcount: {
4014 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
4015 const uint32_t *
Mask =
4017 assert(Mask &&
"Missing call preserved mask for calling convention");
4022 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
4026 if (Subtarget->isThumb())
4029 ARM::tBL_PUSHLR, dl, ResultTys,
4030 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
4031 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
4035 {ReturnAddress, Callee, RegisterMask, Chain}),
4044 unsigned IntNo =
Op.getConstantOperandVal(0);
4048 case Intrinsic::thread_pointer: {
4052 case Intrinsic::arm_cls: {
4053 const SDValue &Operand =
Op.getOperand(1);
4054 const EVT VTy =
Op.getValueType();
4065 case Intrinsic::arm_cls64: {
4068 const SDValue &Operand =
Op.getOperand(1);
4069 const EVT VTy =
Op.getValueType();
4092 case Intrinsic::eh_sjlj_lsda: {
4094 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4099 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
4100 ARMConstantPoolValue *CPV =
4109 if (IsPositionIndependent) {
4115 case Intrinsic::arm_neon_vabs:
4118 case Intrinsic::arm_neon_vabds:
4119 if (
Op.getValueType().isInteger())
4121 Op.getOperand(1),
Op.getOperand(2));
4123 case Intrinsic::arm_neon_vabdu:
4125 Op.getOperand(1),
Op.getOperand(2));
4126 case Intrinsic::arm_neon_vmulls:
4127 case Intrinsic::arm_neon_vmullu: {
4128 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
4130 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4131 Op.getOperand(1),
Op.getOperand(2));
4133 case Intrinsic::arm_neon_vminnm:
4134 case Intrinsic::arm_neon_vmaxnm: {
4135 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
4136 ? ISD::FMINNUM : ISD::FMAXNUM;
4137 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4138 Op.getOperand(1),
Op.getOperand(2));
4140 case Intrinsic::arm_neon_vminu:
4141 case Intrinsic::arm_neon_vmaxu: {
4142 if (
Op.getValueType().isFloatingPoint())
4144 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
4146 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4147 Op.getOperand(1),
Op.getOperand(2));
4149 case Intrinsic::arm_neon_vmins:
4150 case Intrinsic::arm_neon_vmaxs: {
4152 if (!
Op.getValueType().isFloatingPoint()) {
4153 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4155 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4156 Op.getOperand(1),
Op.getOperand(2));
4158 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4159 ? ISD::FMINIMUM : ISD::FMAXIMUM;
4160 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4161 Op.getOperand(1),
Op.getOperand(2));
4163 case Intrinsic::arm_neon_vtbl1:
4165 Op.getOperand(1),
Op.getOperand(2));
4166 case Intrinsic::arm_neon_vtbl2:
4168 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4169 case Intrinsic::arm_mve_pred_i2v:
4170 case Intrinsic::arm_mve_pred_v2i:
4173 case Intrinsic::arm_mve_vreinterpretq:
4176 case Intrinsic::arm_mve_lsll:
4178 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4179 case Intrinsic::arm_mve_asrl:
4181 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4192 if (!Subtarget->hasDataBarrier()) {
4196 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4197 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4208 }
else if (Subtarget->preferISHSTBarriers() &&
4217 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4225 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4227 return Op.getOperand(0);
4230 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4232 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4234 return Op.getOperand(0);
4236 unsigned isData =
Op.getConstantOperandVal(4);
4237 if (Subtarget->isThumb()) {
4239 isRead = ~isRead & 1;
4240 isData = ~isData & 1;
4258 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4266 const SDLoc &dl)
const {
4268 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4270 const TargetRegisterClass *RC;
4272 RC = &ARM::tGPRRegClass;
4274 RC = &ARM::GPRRegClass;
4288 MVT::i32, dl, Root, FIN,
4294 if (!Subtarget->isLittle())
4309 const Value *OrigArg,
4310 unsigned InRegsParamRecordIdx,
4311 int ArgOffset,
unsigned ArgSize)
const {
4325 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4326 unsigned RBegin, REnd;
4331 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4336 ArgOffset = -4 * (ARM::R4 - RBegin);
4343 const TargetRegisterClass *RC =
4346 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4350 MachinePointerInfo(OrigArg, 4 * i));
4355 if (!MemOps.
empty())
4364 unsigned TotalArgRegsSaveSize,
4365 bool ForceMutable)
const {
4367 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4376 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4380bool ARMTargetLowering::splitValueIntoRegisterParts(
4382 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4384 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4389 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
4396SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4398 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4399 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4406 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
4412SDValue ARMTargetLowering::LowerFormalArguments(
4419 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4428 unsigned CurArgIdx = 0;
4440 unsigned ArgRegBegin = ARM::R4;
4441 for (
const CCValAssign &VA : ArgLocs) {
4447 if (!
Flags.isByVal())
4451 unsigned RBegin, REnd;
4453 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4459 int lastInsIndex = -1;
4463 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4466 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4470 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4471 CCValAssign &VA = ArgLocs[i];
4472 if (Ins[VA.
getValNo()].isOrigArg()) {
4473 std::advance(CurOrigArg,
4474 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4486 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4493 MVT::f64, dl, Chain, FIN,
4496 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4504 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4506 const TargetRegisterClass *RC;
4508 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4509 RC = &ARM::HPRRegClass;
4510 else if (RegVT == MVT::f32)
4511 RC = &ARM::SPRRegClass;
4512 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4513 RegVT == MVT::v4bf16)
4514 RC = &ARM::DPRRegClass;
4515 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4516 RegVT == MVT::v8bf16)
4517 RC = &ARM::QPRRegClass;
4518 else if (RegVT == MVT::i32)
4520 : &ARM::GPRRegClass;
4566 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4572 if (index != lastInsIndex)
4574 ISD::ArgFlagsTy
Flags =
Ins[index].Flags;
4580 if (
Flags.isByVal()) {
4581 assert(Ins[index].isOrigArg() &&
4582 "Byval arguments cannot be implicit");
4586 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4620 lastInsIndex = index;
4627 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4628 TotalArgRegsSaveSize);
4632 "secure entry function must not be variadic", dl.
getDebugLoc()));
4642 assert(StackAlign &&
"data layout string is missing stack alignment");
4643 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4652 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4661 return CFP->getValueAPF().isPosZero();
4665 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4668 return CFP->getValueAPF().isPosZero();
4670 }
else if (
Op->getOpcode() == ISD::BITCAST &&
4671 Op->getValueType(0) == MVT::f64) {
4686 const SDLoc &dl)
const {
4688 unsigned C = RHSC->getZExtValue();
4752 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4756 unsigned Mask =
LHS.getConstantOperandVal(1);
4758 uint64_t RHSV = RHSC->getZExtValue();
4759 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4761 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4775 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4778 LHS.getConstantOperandVal(1) < 31) {
4779 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4822 bool Signaling)
const {
4823 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4838std::pair<SDValue, SDValue>
4841 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4853 switch (
Op.getOpcode()) {
4905 return std::make_pair(
Value, OverflowCmp);
4916 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4921 EVT VT =
Op.getValueType();
4926 SDVTList VTs = DAG.
getVTList(
Op.getValueType(), MVT::i32);
4964 EVT VT =
Op.getValueType();
4965 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4968 switch (
Op.getOpcode()) {
4993 EVT VT =
Op.getValueType();
4994 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
5004 switch (
Op->getOpcode()) {
5020 switch (
Op->getOpcode()) {
5039 DAG.
getNode(NewOpcode, dl, MVT::i32,
5050 unsigned Opc =
Cond.getOpcode();
5052 if (
Cond.getResNo() == 1 &&
5060 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5061 EVT VT =
Op.getValueType();
5063 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
5072 const ConstantSDNode *CMOVTrue =
5074 const ConstantSDNode *CMOVFalse =
5077 if (CMOVTrue && CMOVFalse) {
5083 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5085 False = SelectFalse;
5086 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5092 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5093 Cond.getOperand(3), DAG);
5108 bool &swpCmpOps,
bool &swpVselOps) {
5136 swpCmpOps = !swpCmpOps;
5137 swpVselOps = !swpVselOps;
5160 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5162 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5164 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5199 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5201 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5222 EVT VT =
Op.getValueType();
5244 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5257 int64_t PosVal = std::max(Val1, Val2);
5258 int64_t NegVal = std::min(Val1, Val2);
5305 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5310 if (*K != KTmp || V != VTmp)
5321bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5323 return !Subtarget->hasVFP2Base();
5325 return !Subtarget->hasFP64();
5327 return !Subtarget->hasFullFP16();
5332 EVT VT =
Op.getValueType();
5336 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5348 if (VT == MVT::i32 &&
5368 if (
Op.getValueType().isInteger()) {
5376 LHS.getValueType() ==
RHS.getValueType()) {
5377 EVT VT =
LHS.getValueType();
5383 Shift = DAG.
getNOT(dl, Shift, VT);
5389 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5390 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5393 unsigned Opcode = 0;
5395 if (TVal == ~FVal) {
5397 }
else if (TVal == ~FVal + 1) {
5399 }
else if (TVal + 1 == FVal) {
5401 }
else if (TVal == FVal + 1) {
5432 EVT VT =
TrueVal.getValueType();
5433 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5437 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5442 if (!
RHS.getNode()) {
5448 if (
LHS.getValueType() == MVT::i32) {
5459 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5460 TrueVal.getValueType() == MVT::f32 ||
5461 TrueVal.getValueType() == MVT::f64)) {
5475 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5485 if (Subtarget->hasFPARMv8Base() &&
5487 (
TrueVal.getValueType() == MVT::f16 ||
5488 TrueVal.getValueType() == MVT::f32 ||
5489 TrueVal.getValueType() == MVT::f64)) {
5490 bool swpCmpOps =
false;
5491 bool swpVselOps =
false;
5505 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5508 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5518 if (!
N->hasOneUse())
5521 if (!
N->getNumValues())
5523 EVT VT =
Op.getValueType();
5524 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5541 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5542 Ld->getPointerInfo(), Ld->getAlign(),
5543 Ld->getMemOperand()->getFlags());
5561 DAG.
getLoad(MVT::i32, dl, Ld->getChain(),
Ptr, Ld->getPointerInfo(),
5562 Ld->getAlign(), Ld->getMemOperand()->getFlags());
5564 EVT PtrType =
Ptr.getValueType();
5567 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5568 Ld->getPointerInfo().getWithOffset(4),
5570 Ld->getMemOperand()->getFlags());
5588 bool LHSSeenZero =
false;
5590 bool RHSSeenZero =
false;
5592 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5603 if (
LHS.getValueType() == MVT::f32) {
5621 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5649 unsigned Opc =
Cond.getOpcode();
5651 !Subtarget->isThumb1Only();
5652 if (
Cond.getResNo() == 1 &&
5662 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5668 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5685 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5690 if (!
RHS.getNode()) {
5698 unsigned Opc =
LHS.getOpcode();
5700 !Subtarget->isThumb1Only();
5712 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5719 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5726 if (
LHS.getValueType() == MVT::i32) {
5732 SDNodeFlags
Flags =
Op->getFlags();
5733 if (
Flags.hasNoNaNs() &&
5738 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5769 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5775 Addr,
Op.getOperand(2), JTI);
5779 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5786 DAG.
getLoad(PTy, dl, Chain, Addr,
5794 EVT VT =
Op.getValueType();
5797 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5798 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5806 const EVT OpTy =
Op.getOperand(0).getValueType();
5807 if (OpTy == MVT::v4f32)
5809 else if (OpTy == MVT::v4f16 && HasFullFP16)
5811 else if (OpTy == MVT::v8f16 && HasFullFP16)
5816 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5819 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5824 EVT VT =
Op.getValueType();
5828 bool IsStrict =
Op->isStrictFPOpcode();
5829 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5831 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5844 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5845 CallOptions, Loc, Chain);
5855 Loc,
Op.getValueType(), SrcVal);
5864 EVT VT =
Op.getValueType();
5866 EVT FromVT =
Op.getOperand(0).getValueType();
5868 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5870 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5871 Subtarget->hasFP64())
5873 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5874 Subtarget->hasFullFP16())
5876 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5877 Subtarget->hasMVEFloatOps())
5879 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5880 Subtarget->hasMVEFloatOps())
5883 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5900 EVT VT =
Op.getValueType();
5903 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5909 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5910 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5911 "Invalid type for custom lowering!");
5916 if (VT == MVT::v4f32)
5917 DestVecType = MVT::v4i32;
5918 else if (VT == MVT::v4f16 && HasFullFP16)
5919 DestVecType = MVT::v4i16;
5920 else if (VT == MVT::v8f16 && HasFullFP16)
5921 DestVecType = MVT::v8i16;
5927 switch (
Op.getOpcode()) {
5939 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5944 EVT VT =
Op.getValueType();
5947 if (isUnsupportedFloatingType(VT)) {
5957 CallOptions, SDLoc(
Op)).first;
5968 EVT VT =
Op.getValueType();
5970 bool InGPR = Tmp0.
getOpcode() == ISD::BITCAST ||
5972 bool UseNEON = !InGPR && Subtarget->hasNEON();
5979 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5982 DAG.
getNode(ISD::BITCAST, dl, OpVT, Mask),
5986 if (SrcVT == MVT::f32) {
5990 DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1),
5992 }
else if (VT == MVT::f32)
5994 DAG.
getNode(ISD::BITCAST, dl, MVT::v1i64, Tmp1),
5996 Tmp0 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp0);
5997 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1);
6008 if (VT == MVT::f32) {
6009 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::v2f32, Res);
6013 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Res);
6020 if (SrcVT == MVT::f64)
6023 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp1);
6029 if (VT == MVT::f32) {
6031 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
6032 return DAG.
getNode(ISD::BITCAST, dl, MVT::f32,
6050 EVT VT =
Op.getValueType();
6052 unsigned Depth =
Op.getConstantOperandVal(0);
6054 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
6058 MachinePointerInfo());
6067 const ARMBaseRegisterInfo &ARI =
6068 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
6073 EVT VT =
Op.getValueType();
6075 unsigned Depth =
Op.getConstantOperandVal(0);
6080 MachinePointerInfo());
6088 return StringSwitch<Register>(
RegName)
6089 .Case(
"sp", ARM::SP)
6100 assert(
N->getValueType(0) == MVT::i64
6101 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6104 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6144 const APInt &APIntIndex = Index->getAPIntValue();
6146 NewIndex *= APIntIndex;
6158 SDValue BitCast = DAG.
getNode(ISD::BITCAST, dl, VecVT, ExtractSrc);
6175 EVT SrcVT =
Op.getValueType();
6176 EVT DstVT =
N->getValueType(0);
6178 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6179 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6180 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6183 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6184 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6185 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6192 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6203 return DAG.
getNode(ISD::BITCAST, dl, DstVT,
6237 return DAG.
getNode(ISD::BITCAST, dl, VT, Vmov);
6245 EVT VT =
Op.getValueType();
6288 EVT VT =
Op.getValueType();
6330 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6382 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6410 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6440 EVT VT =
N->getValueType(0);
6441 if (VT.
isVector() && ST->hasNEON()) {
6450 if (ElemTy == MVT::i8) {
6458 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6461 unsigned NumBits = ElemTy.getSizeInBits();
6473 if (ElemTy == MVT::i64) {
6486 if (!ST->hasV6T2Ops())
6495 EVT VT =
N->getValueType(0);
6498 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6499 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6500 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6501 "Unexpected type for custom ctpop lowering");
6509 unsigned EltSize = 8;
6531 while (
Op.getOpcode() == ISD::BITCAST)
6532 Op =
Op.getOperand(0);
6534 APInt SplatBits, SplatUndef;
6535 unsigned SplatBitSize;
6538 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6540 SplatBitSize > ElementBits)
6551 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6555 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6566 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6571 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6572 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6581 EVT VT =
N->getValueType(0);
6603 "unexpected vector shift opcode");
6605 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6606 unsigned VShiftOpc =
6608 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6614 EVT ShiftVT =
N->getOperand(1).getValueType();
6617 unsigned VShiftOpc =
6619 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6624 EVT VT =
N->getValueType(0);
6633 "Unknown shift to lower!");
6635 unsigned ShOpc =
N->getOpcode();
6636 if (ST->hasMVEIntegerOps()) {
6666 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6680 if (ST->isThumb1Only())
6685 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6701 bool Invert =
false;
6708 EVT VT =
Op.getValueType();
6716 assert(ST->hasMVEIntegerOps() &&
6717 "No hardware support for integer vector comparison!");
6719 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6742 Merged = DAG.
getNode(ISD::BITCAST, dl, CmpVT, Merged);
6744 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6754 switch (SetCCOpcode) {
6758 if (ST->hasMVEFloatOps()) {
6761 Invert =
true; [[fallthrough]];
6766 case ISD::SETLT: Swap =
true; [[fallthrough]];
6770 case ISD::SETLE: Swap =
true; [[fallthrough]];
6786 Result = DAG.
getNOT(dl, Result, VT);
6789 case ISD::SETUO: Invert =
true; [[fallthrough]];
6798 Result = DAG.
getNOT(dl, Result, VT);
6804 switch (SetCCOpcode) {
6807 if (ST->hasMVEIntegerOps()) {
6810 Invert =
true; [[fallthrough]];
6813 case ISD::SETLT: Swap =
true; [[fallthrough]];
6815 case ISD::SETLE: Swap =
true; [[fallthrough]];
6832 if (AndOp.getNode() && AndOp.getOpcode() == ISD::BITCAST)
6835 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6836 Op0 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(0));
6837 Op1 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(1));
6840 Result = DAG.
getNOT(dl, Result, VT);
6874 Result = DAG.
getNOT(dl, Result, VT);
6886 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6913 unsigned OpCmode, Imm;
6924 switch (SplatBitSize) {
6929 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6932 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6937 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6938 if ((SplatBits & ~0xff) == 0) {
6944 if ((SplatBits & ~0xff00) == 0) {
6947 Imm = SplatBits >> 8;
6957 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6958 if ((SplatBits & ~0xff) == 0) {
6964 if ((SplatBits & ~0xff00) == 0) {
6967 Imm = SplatBits >> 8;
6970 if ((SplatBits & ~0xff0000) == 0) {
6973 Imm = SplatBits >> 16;
6976 if ((SplatBits & ~0xff000000) == 0) {
6979 Imm = SplatBits >> 24;
6986 if ((SplatBits & ~0xffff) == 0 &&
6987 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6990 Imm = SplatBits >> 8;
6998 if ((SplatBits & ~0xffffff) == 0 &&
6999 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
7002 Imm = SplatBits >> 16;
7018 unsigned ImmMask = 1;
7020 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
7021 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
7023 }
else if ((SplatBits & BitMask) != 0) {
7032 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
7046 EVT VT =
Op.getValueType();
7047 bool IsDouble = (VT == MVT::f64);
7053 if (
ST->genExecuteOnly()) {
7055 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
7056 "Unexpected architecture");
7079 if (!
ST->hasVFP3Base())
7084 if (IsDouble && !Subtarget->hasFP64())
7091 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7109 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7118 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7129 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
7146 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
7172 unsigned ExpectedElt = Imm;
7173 for (
unsigned i = 1; i < NumElts; ++i) {
7177 if (ExpectedElt == NumElts)
7180 if (M[i] < 0)
continue;
7181 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7189 bool &ReverseVEXT,
unsigned &Imm) {
7191 ReverseVEXT =
false;
7202 unsigned ExpectedElt = Imm;
7203 for (
unsigned i = 1; i < NumElts; ++i) {
7207 if (ExpectedElt == NumElts * 2) {
7212 if (M[i] < 0)
continue;
7213 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7228 return VT == MVT::v8i8 && M.size() == 8;
7233 if (Mask.size() == Elements * 2)
7234 return Index / Elements;
7235 return Mask[Index] == 0 ? 0 : 1;
7265 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7273 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7275 for (
unsigned j = 0; j < NumElts; j += 2) {
7276 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7277 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7282 if (M.size() == NumElts*2)
7297 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7300 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7302 for (
unsigned j = 0; j < NumElts; j += 2) {
7303 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7304 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7309 if (M.size() == NumElts*2)
7329 if (M.size() != NumElts && M.size() != NumElts*2)
7332 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7334 for (
unsigned j = 0; j < NumElts; ++j) {
7335 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7340 if (M.size() == NumElts*2)
7359 if (M.size() != NumElts && M.size() != NumElts*2)
7362 unsigned Half = NumElts / 2;
7363 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7365 for (
unsigned j = 0; j < NumElts; j += Half) {
7366 unsigned Idx = WhichResult;
7367 for (
unsigned k = 0; k < Half; ++k) {
7368 int MIdx = M[i + j + k];
7369 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7376 if (M.size() == NumElts*2)
7400 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7403 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7405 unsigned Idx = WhichResult * NumElts / 2;
7406 for (
unsigned j = 0; j < NumElts; j += 2) {
7407 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7408 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7414 if (M.size() == NumElts*2)
7433 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7436 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7438 unsigned Idx = WhichResult * NumElts / 2;
7439 for (
unsigned j = 0; j < NumElts; j += 2) {
7440 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7441 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7447 if (M.size() == NumElts*2)
7460 unsigned &WhichResult,
7463 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7465 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7467 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7485 if (NumElts != M.size())
7489 for (
unsigned i = 0; i != NumElts; ++i)
7490 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7499 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7507 int Ofs = Top ? 1 : 0;
7508 int Upper = SingleSource ? 0 : NumElts;
7509 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7510 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7512 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7521 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7530 unsigned Offset = Top ? 0 : 1;
7531 unsigned N = SingleSource ? 0 : NumElts;
7532 for (
unsigned i = 0; i < NumElts; i += 2) {
7533 if (M[i] >= 0 && M[i] != (
int)i)
7535 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7544 if (NumElts != M.size())
7552 unsigned Off0 = rev ? NumElts / 2 : 0;
7553 unsigned Off1 = rev ? 0 : NumElts / 2;
7554 for (
unsigned i = 0; i < NumElts; i += 2) {
7555 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7557 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7573 if (!ST->hasMVEFloatOps())
7578 if (VT != MVT::v8f16)
7599 for (
unsigned i = 1; i < 4; i++) {
7626 if (!ST->hasMVEFloatOps())
7631 if (VT != MVT::v4f32)
7647 for (
unsigned i = 1; i < 4; i++) {
7649 return Trunc.
getOpcode() == ISD::FP_EXTEND &&
7670 Val =
N->getAsZExtVal();
7672 if (ST->isThumb1Only()) {
7673 if (Val <= 255 || ~Val <= 255)
7685 EVT VT =
Op.getValueType();
7687 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7691 unsigned BitsPerBool;
7695 }
else if (NumElts == 4) {
7698 }
else if (NumElts == 8) {
7701 }
else if (NumElts == 16) {
7712 return U.get().isUndef() || U.get() == FirstOp;
7720 unsigned Bits32 = 0;
7721 for (
unsigned i = 0; i < NumElts; ++i) {
7725 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7727 Bits32 |= BoolMask << (i * BitsPerBool);
7733 for (
unsigned i = 0; i < NumElts; ++i) {
7746 if (!ST->hasMVEIntegerOps())
7750 EVT VT =
Op.getValueType();
7760 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7764 for (
unsigned I = 2;
I < NumElts;
I++) {
7780 switch (
N->getOpcode()) {
7791 return N->getOperand(1).getNode() ==
Op;
7793 switch (
N->getConstantOperandVal(0)) {
7794 case Intrinsic::arm_mve_add_predicated:
7795 case Intrinsic::arm_mve_mul_predicated:
7796 case Intrinsic::arm_mve_qadd_predicated:
7797 case Intrinsic::arm_mve_vhadd:
7798 case Intrinsic::arm_mve_hadd_predicated:
7799 case Intrinsic::arm_mve_vqdmulh:
7800 case Intrinsic::arm_mve_qdmulh_predicated:
7801 case Intrinsic::arm_mve_vqrdmulh:
7802 case Intrinsic::arm_mve_qrdmulh_predicated:
7803 case Intrinsic::arm_mve_vqdmull:
7804 case Intrinsic::arm_mve_vqdmull_predicated:
7806 case Intrinsic::arm_mve_sub_predicated:
7807 case Intrinsic::arm_mve_qsub_predicated:
7808 case Intrinsic::arm_mve_vhsub:
7809 case Intrinsic::arm_mve_hsub_predicated:
7810 return N->getOperand(2).getNode() ==
Op;
7825 EVT VT =
Op.getValueType();
7833 APInt SplatBits, SplatUndef;
7834 unsigned SplatBitSize;
7836 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7843 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7845 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7846 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7847 : SplatBitSize == 16 ? MVT::v8i16
7854 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7855 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7860 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7868 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7870 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7878 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7888 if (
ST->hasMVEIntegerOps() &&
7889 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7890 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7891 : SplatBitSize == 16 ? MVT::v8i16
7908 bool isOnlyLowElement =
true;
7909 bool usesOnlyOneValue =
true;
7910 bool hasDominantValue =
false;
7915 DenseMap<SDValue, unsigned> ValueCounts;
7917 for (
unsigned i = 0; i < NumElts; ++i) {
7922 isOnlyLowElement =
false;
7926 unsigned &
Count = ValueCounts[
V];
7929 if (++
Count > (NumElts / 2)) {
7930 hasDominantValue =
true;
7934 if (ValueCounts.
size() != 1)
7935 usesOnlyOneValue =
false;
7936 if (!
Value.getNode() && !ValueCounts.
empty())
7939 if (ValueCounts.
empty())
7951 if (hasDominantValue && EltSize <= 32) {
7960 ConstantSDNode *constIndex;
7967 if (VT !=
Value->getOperand(0).getValueType()) {
7980 if (!usesOnlyOneValue) {
7983 for (
unsigned I = 0;
I < NumElts; ++
I) {
7988 Ops.push_back(
Op.getOperand(
I));
7998 assert(FVT == MVT::f32 || FVT == MVT::f16);
7999 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
8000 for (
unsigned i = 0; i < NumElts; ++i)
8001 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, IVT,
8005 Val = LowerBUILD_VECTOR(Val, DAG, ST);
8007 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8009 if (usesOnlyOneValue) {
8036 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
8056 if (EltSize >= 32) {
8062 for (
unsigned i = 0; i < NumElts; ++i)
8063 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, EltVT,
Op.getOperand(i)));
8065 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8076 for (
unsigned i = 0 ; i < NumElts; ++i) {
8095 EVT VT =
Op.getValueType();
8098 struct ShuffleSourceInfo {
8100 unsigned MinElt = std::numeric_limits<unsigned>::max();
8101 unsigned MaxElt = 0;
8111 int WindowScale = 1;
8113 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8121 for (
unsigned i = 0; i < NumElts; ++i) {
8136 SDValue SourceVec =
V.getOperand(0);
8138 if (Source == Sources.
end())
8142 unsigned EltNo =
V.getConstantOperandVal(1);
8149 if (Sources.
size() > 2)
8155 for (
auto &Source : Sources) {
8156 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8157 if (SrcEltTy.
bitsLT(SmallestEltTy))
8158 SmallestEltTy = SrcEltTy;
8160 unsigned ResMultiplier =
8168 for (
auto &Src : Sources) {
8169 EVT SrcVT = Src.ShuffleVec.getValueType();
8173 if (SrcVTSize == VTSize)
8182 if (SrcVTSize < VTSize) {
8183 if (2 * SrcVTSize != VTSize)
8189 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8193 if (SrcVTSize != 2 * VTSize)
8196 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8201 if (Src.MinElt >= NumSrcElts) {
8206 Src.WindowBase = -NumSrcElts;
8207 }
else if (Src.MaxElt < NumSrcElts) {
8224 Src.WindowBase = -Src.MinElt;
8231 for (
auto &Src : Sources) {
8232 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8233 if (SrcEltTy == SmallestEltTy)
8238 Src.WindowBase *= Src.WindowScale;
8243 for (
auto Src : Sources)
8244 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8252 if (
Entry.isUndef())
8261 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8264 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8268 int *LaneMask = &
Mask[i * ResMultiplier];
8270 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8271 ExtractBase += NumElts * (Src - Sources.begin());
8272 for (
int j = 0;
j < LanesDefined; ++
j)
8273 LaneMask[j] = ExtractBase + j;
8279 assert(Sources.size() <= 2 &&
"Too many sources!");
8282 for (
unsigned i = 0; i < Sources.size(); ++i)
8311 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8331 unsigned PFIndexes[4];
8332 for (
unsigned i = 0; i != 4; ++i) {
8336 PFIndexes[i] = M[i];
8340 unsigned PFTableIndex =
8341 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8343 unsigned Cost = (PFEntry >> 30);
8349 bool ReverseVEXT, isV_UNDEF;
8350 unsigned Imm, WhichResult;
8353 if (EltSize >= 32 ||
8360 else if (Subtarget->hasNEON() &&
8365 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8368 else if (Subtarget->hasMVEIntegerOps() &&
8372 else if (Subtarget->hasMVEIntegerOps() &&
8386 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8387 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8388 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8391 if (LHSID == (1*9+2)*9+3)
return LHS;
8392 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8449 for (
int I : ShuffleMask)
8462 EVT VT =
Op.getValueType();
8464 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8465 "Expect an v8i16/v16i8 type");
8471 std::vector<int> NewMask;
8475 NewMask.push_back(i);
8515 if (VT != MVT::v16i1)
8526 return DAG.
getNode(ISD::BITCAST, dl, NewVT, PredAsVector);
8531 EVT VT =
Op.getValueType();
8535 assert(ST->hasMVEIntegerOps() &&
8536 "No support for vector shuffle of boolean predicates");
8562 "Expected identical vector type in expanded i1 shuffle!");
8566 PredAsVector2, ShuffleMask);
8571 if (VT == MVT::v2i1) {
8588 EVT VT =
Op.getValueType();
8592 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8593 "Unexpected vector type");
8595 int QuarterSize = NumElts / 4;
8604 for (
int i = 0; i <
Length; i++) {
8605 if (ShuffleMask[Start + i] >= 0) {
8606 if (ShuffleMask[Start + i] %
Length != i)
8608 MovIdx = ShuffleMask[Start + i] /
Length;
8616 for (
int i = 1; i <
Length; i++) {
8617 if (ShuffleMask[Start + i] >= 0 &&
8618 (ShuffleMask[Start + i] /
Length != MovIdx ||
8619 ShuffleMask[Start + i] %
Length != i))
8625 for (
int Part = 0; Part < 4; ++Part) {
8627 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8641 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8646 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8648 for (
int Part = 0; Part < 4; ++Part)
8649 for (
int i = 0; i < QuarterSize; i++)
8651 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8653 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8656 for (
int Part = 0; Part < 4; ++Part)
8672 EVT VT =
Op.getValueType();
8684 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8688 if (Mask[i] != i + BaseOffset) {
8689 if (OffElement == -1)
8695 return NonUndef > 2 && OffElement != -1;
8699 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8701 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8712 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8723 EVT VT =
Op.getValueType();
8727 if (ST->hasMVEIntegerOps() && EltSize == 1)
8738 if (EltSize <= 32) {
8742 if (Lane == -1) Lane = 0;
8753 bool IsScalarToVector =
true;
8756 IsScalarToVector =
false;
8759 if (IsScalarToVector)
8766 bool ReverseVEXT =
false;
8768 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8792 unsigned WhichResult = 0;
8793 bool isV_UNDEF =
false;
8794 if (ST->hasNEON()) {
8796 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8803 if (ST->hasMVEIntegerOps()) {
8838 }) &&
"Unexpected shuffle index into UNDEF operand!");
8841 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8844 assert((WhichResult == 0) &&
8845 "In-place shuffle of concat can only have one result!");
8854 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8858 for (
bool Top : {
false,
true}) {
8859 for (
bool SingleSource : {
false,
true}) {
8860 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8865 SingleSource ? V1 : V2);
8881 unsigned PFIndexes[4];
8882 for (
unsigned i = 0; i != 4; ++i) {
8883 if (ShuffleMask[i] < 0)
8886 PFIndexes[i] = ShuffleMask[i];
8890 unsigned PFTableIndex =
8891 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8893 unsigned Cost = (PFEntry >> 30);
8899 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8900 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8910 if (EltSize >= 32) {
8915 V1 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V1);
8916 V2 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V2);
8918 for (
unsigned i = 0; i < NumElts; ++i) {
8919 if (ShuffleMask[i] < 0)
8923 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8928 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8931 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8935 if (ST->hasNEON() && VT == MVT::v8i8)
8939 if (ST->hasMVEIntegerOps())
8948 EVT VecVT =
Op.getOperand(0).getValueType();
8951 assert(ST->hasMVEIntegerOps() &&
8952 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8956 unsigned Lane =
Op.getConstantOperandVal(2);
8957 unsigned LaneWidth =
8959 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8977 if (Subtarget->hasMVEIntegerOps() &&
8978 Op.getValueType().getScalarSizeInBits() == 1)
9002 IVecIn, IElt, Lane);
9003 return DAG.
getNode(ISD::BITCAST, dl, VecVT, IVecOut);
9011 EVT VecVT =
Op.getOperand(0).getValueType();
9014 assert(ST->hasMVEIntegerOps() &&
9015 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9019 unsigned Lane =
Op.getConstantOperandVal(1);
9020 unsigned LaneWidth =
9051 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
9052 "Unexpected custom CONCAT_VECTORS lowering");
9054 "Unexpected custom CONCAT_VECTORS lowering");
9055 assert(ST->hasMVEIntegerOps() &&
9056 "CONCAT_VECTORS lowering only supported for MVE");
9060 EVT Op2VT = V2.getValueType();
9061 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9062 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9063 "Unexpected i1 concat operations!");
9076 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9090 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9091 EVT NewVT = NewV.getValueType();
9092 EVT ConcatVT = ConVec.getValueType();
9093 unsigned ExtScale = 1;
9094 if (NewVT == MVT::v2f64) {
9108 ConVec = ExtractInto(NewV1, ConVec, j);
9109 ConVec = ExtractInto(NewV2, ConVec, j);
9119 while (ConcatOps.
size() > 1) {
9120 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
9123 ConcatOps[
I / 2] = ConcatPair(V1, V2);
9127 return ConcatOps[0];
9132 EVT VT =
Op->getValueType(0);
9138 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9139 "unexpected CONCAT_VECTORS");
9146 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op0),
9150 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op1),
9152 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Val);
9160 EVT VT =
Op.getValueType();
9166 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9167 assert(ST->hasMVEIntegerOps() &&
9168 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9178 EVT SubVT = MVT::v4i32;
9180 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9195 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9211 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9212 EVT VT =
N->getValueType(0);
9213 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9214 "Expected a vector i1 type!");
9216 EVT FromVT =
Op.getValueType();
9227 if (!Subtarget->hasMVEIntegerOps())
9230 EVT ToVT =
N->getValueType(0);
9273 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9275 EVT FromVT =
N->getOperand(0).getValueType();
9276 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9287 if (!Subtarget->hasMVEIntegerOps())
9292 EVT ToVT =
N->getValueType(0);
9293 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9296 EVT FromVT =
Op.getValueType();
9297 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9308 SDValue Ext1 = Ext.getValue(1);
9311 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9312 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9324 EVT VT =
N->getValueType(0);
9325 if (VT == MVT::v2i64 &&
N->getOpcode() == ISD::BITCAST) {
9326 SDNode *BVN =
N->getOperand(0).getNode();
9331 unsigned HiElt = 1 - LoElt;
9336 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9352 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9353 SDNode *Elt =
N->getOperand(i).getNode();
9356 unsigned HalfSize = EltSize / 2;
9358 if (!
isIntN(HalfSize,
C->getSExtValue()))
9361 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9400 switch (OrigSimpleTy) {
9416 unsigned ExtOpcode) {
9439 if (ExtendedTy == LD->getMemoryVT())
9440 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9441 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9442 LD->getMemOperand()->getFlags());
9448 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9449 LD->getMemoryVT(), LD->getAlign(),
9450 LD->getMemOperand()->getFlags());
9463 N->getOperand(0)->getValueType(0),
9469 "Expected extending load");
9475 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9483 if (
N->getOpcode() == ISD::BITCAST) {
9484 SDNode *BVN =
N->getOperand(0).getNode();
9486 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9494 EVT VT =
N->getValueType(0);
9500 for (
unsigned i = 0; i != NumElts; ++i) {
9501 const APInt &CInt =
N->getConstantOperandAPInt(i);
9510 unsigned Opcode =
N->getOpcode();
9512 SDNode *N0 =
N->getOperand(0).getNode();
9513 SDNode *N1 =
N->getOperand(1).getNode();
9521 unsigned Opcode =
N->getOpcode();
9523 SDNode *N0 =
N->getOperand(0).getNode();
9524 SDNode *N1 =
N->getOperand(1).getNode();
9534 EVT VT =
Op.getValueType();
9536 "unexpected type for custom-lowering ISD::MUL");
9537 SDNode *N0 =
Op.getOperand(0).getNode();
9538 SDNode *N1 =
Op.getOperand(1).getNode();
9539 unsigned NewOpc = 0;
9543 if (isN0SExt && isN1SExt)
9548 if (isN0ZExt && isN1ZExt)
9550 else if (isN1SExt || isN1ZExt) {
9567 if (VT == MVT::v2i64)
9584 "unexpected types for extended operands to VMULL");
9585 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9601 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N00), Op1),
9603 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N01), Op1));
9620 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9627 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32,
X);
9630 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32,
X);
9654 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9657 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9665 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9668 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9678 EVT VT =
Op.getValueType();
9679 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9680 "unexpected type for custom-lowering ISD::SDIV");
9687 if (VT == MVT::v8i8) {
9715 EVT VT =
Op.getValueType();
9716 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9717 "unexpected type for custom-lowering ISD::UDIV");
9724 if (VT == MVT::v8i8) {
9763 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9766 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9770 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9778 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9781 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9791 EVT VT =
N->getValueType(0);
9805 Op.getOperand(1), Carry);
9819 Op.getOperand(1), Carry);
9834 assert(Subtarget->isTargetDarwin());
9853 if (ShouldUseSRet) {
9855 const uint64_t ByteSize =
DL.getTypeAllocSize(RetTy);
9856 const Align StackAlign =
DL.getPrefTypeAlign(RetTy);
9861 Entry.IsSExt =
false;
9862 Entry.IsZExt =
false;
9863 Entry.IsSRet =
true;
9864 Args.push_back(Entry);
9868 Args.emplace_back(Arg, ArgTy);
9871 (ArgVT == MVT::f64) ? RTLIB::SINCOS_STRET_F64 : RTLIB::SINCOS_STRET_F32;
9876 TargetLowering::CallLoweringInfo CLI(DAG);
9879 .
setCallee(CC, RetTy, Callee, std::move(Args))
9881 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
9884 return CallResult.first;
9887 DAG.
getLoad(ArgVT, dl, CallResult.second, SRet, MachinePointerInfo());
9895 SDVTList Tys = DAG.
getVTList(ArgVT, ArgVT);
9903 EVT VT =
Op.getValueType();
9904 assert((VT == MVT::i32 || VT == MVT::i64) &&
9905 "unexpected type for custom lowering DIV");
9911 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9913 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9920 for (
auto AI : {1, 0}) {
9922 Args.emplace_back(Operand,
9930 ES, std::move(Args));
9940ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9948 const bool MinSize =
ST.hasMinSize();
9949 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9950 :
ST.hasDivideInARMMode();
9954 if (
N->getOperand(0).getValueType().isVector())
9959 if (!(MinSize && HasDivide))
9972 if (Divisor.
sgt(128))
9980 assert(
Op.getValueType() == MVT::i32 &&
9981 "unexpected type for custom lowering DIV");
9987 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9993 if (
N->getValueType(0) == MVT::i32)
10001void ARMTargetLowering::ExpandDIV_Windows(
10006 assert(
Op.getValueType() == MVT::i64 &&
10007 "unexpected type for custom lowering DIV");
10024 EVT MemVT = LD->getMemoryVT();
10025 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10026 MemVT == MVT::v16i1) &&
10027 "Expected a predicate type!");
10028 assert(MemVT ==
Op.getValueType());
10030 "Expected a non-extending load");
10031 assert(LD->isUnindexed() &&
"Expected a unindexed load");
10045 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
10047 LD->getMemOperand());
10054 if (MemVT != MVT::v16i1)
10063 EVT MemVT =
LD->getMemoryVT();
10064 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10066 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10067 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
10068 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10072 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10082 EVT MemVT = ST->getMemoryVT();
10083 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10084 MemVT == MVT::v16i1) &&
10085 "Expected a predicate type!");
10086 assert(MemVT == ST->getValue().getValueType());
10087 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10088 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10093 SDValue Build = ST->getValue();
10094 if (MemVT != MVT::v16i1) {
10113 ST->getChain(), dl, GRP, ST->getBasePtr(),
10115 ST->getMemOperand());
10121 EVT MemVT = ST->getMemoryVT();
10122 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10124 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10140 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10141 MemVT, ST->getMemOperand());
10142 }
else if (Subtarget->hasMVEIntegerOps() &&
10143 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10144 MemVT == MVT::v16i1))) {
10159 MVT VT =
Op.getSimpleValueType();
10161 SDValue PassThru =
N->getPassThru();
10172 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10173 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10174 N->getExtensionType(),
N->isExpandingLoad());
10176 bool PassThruIsCastZero = (PassThru.
getOpcode() == ISD::BITCAST ||
10179 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10186 if (!ST->hasMVEIntegerOps())
10190 unsigned BaseOpcode = 0;
10191 switch (
Op->getOpcode()) {
10193 case ISD::VECREDUCE_FADD: BaseOpcode =
ISD::FADD;
break;
10194 case ISD::VECREDUCE_FMUL: BaseOpcode =
ISD::FMUL;
break;
10195 case ISD::VECREDUCE_MUL: BaseOpcode =
ISD::MUL;
break;
10196 case ISD::VECREDUCE_AND: BaseOpcode =
ISD::AND;
break;
10197 case ISD::VECREDUCE_OR: BaseOpcode =
ISD::OR;
break;
10198 case ISD::VECREDUCE_XOR: BaseOpcode =
ISD::XOR;
break;
10199 case ISD::VECREDUCE_FMAX: BaseOpcode = ISD::FMAXNUM;
break;
10200 case ISD::VECREDUCE_FMIN: BaseOpcode = ISD::FMINNUM;
break;
10207 unsigned NumActiveLanes = NumElts;
10209 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10210 NumActiveLanes == 2) &&
10211 "Only expected a power 2 vector size");
10215 while (NumActiveLanes > 4) {
10218 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10219 NumActiveLanes /= 2;
10223 if (NumActiveLanes == 4) {
10233 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10234 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10235 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10241 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10245 if (EltVT !=
Op->getValueType(0))
10252 if (!ST->hasMVEFloatOps())
10259 if (!ST->hasNEON())
10267 unsigned PairwiseIntrinsic = 0;
10268 switch (
Op->getOpcode()) {
10271 case ISD::VECREDUCE_UMIN:
10272 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10274 case ISD::VECREDUCE_UMAX:
10275 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10277 case ISD::VECREDUCE_SMIN:
10278 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10280 case ISD::VECREDUCE_SMAX:
10281 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10287 unsigned NumActiveLanes = NumElts;
10289 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10290 NumActiveLanes == 2) &&
10291 "Only expected a power 2 vector size");
10297 VT =
Lo.getValueType();
10299 NumActiveLanes /= 2;
10303 while (NumActiveLanes > 1) {
10305 NumActiveLanes /= 2;
10312 if (EltVT !=
Op.getValueType()) {
10313 unsigned Extend = 0;
10314 switch (
Op->getOpcode()) {
10317 case ISD::VECREDUCE_UMIN:
10318 case ISD::VECREDUCE_UMAX:
10321 case ISD::VECREDUCE_SMIN:
10322 case ISD::VECREDUCE_SMAX:
10326 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10371 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10377 SDLoc dl(V.getNode());
10378 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10388 assert(
N->getValueType(0) == MVT::i64 &&
10389 "AtomicCmpSwap on types less than 64 should be legal");
10398 ARM::CMP_SWAP_64,
SDLoc(
N),
10399 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10418 EVT VT =
Op.getValueType();
10427 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10429 Chain, IsSignaling);
10430 if (!
RHS.getNode()) {
10446 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10448 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10449 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10466 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10469 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10482 if (!IsSigned && Subtarget->isThumb1Only()) {
10500 Sub1Result, Sub1Result, Flags1);
10515 if (
Op.getValueType() != MVT::i32)
10538 bool CanUseAdd =
false;
10579 GTCondValue, Flags);
10584 LTCondValue, Flags);
10586 if (
Op.getValueType() != MVT::i32)
10594 switch (
Op.getOpcode()) {
10603 case ISD::BRCOND:
return LowerBRCOND(
Op, DAG);
10604 case ISD::BR_CC:
return LowerBR_CC(
Op, DAG);
10605 case ISD::BR_JT:
return LowerBR_JT(
Op, DAG);
10626 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10630 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10631 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10651 case ISD::SET_ROUNDING:
return LowerSET_ROUNDING(
Op, DAG);
10652 case ISD::SET_FPMODE:
10653 return LowerSET_FPMODE(
Op, DAG);
10654 case ISD::RESET_FPMODE:
10655 return LowerRESET_FPMODE(
Op, DAG);
10658 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10659 return LowerDIV_Windows(
Op, DAG,
true);
10662 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10663 return LowerDIV_Windows(
Op, DAG,
false);
10670 return LowerSignedALUO(
Op, DAG);
10673 return LowerUnsignedALUO(
Op, DAG);
10685 case ISD::VECREDUCE_MUL:
10686 case ISD::VECREDUCE_AND:
10687 case ISD::VECREDUCE_OR:
10688 case ISD::VECREDUCE_XOR:
10690 case ISD::VECREDUCE_FADD:
10691 case ISD::VECREDUCE_FMUL:
10692 case ISD::VECREDUCE_FMIN:
10693 case ISD::VECREDUCE_FMAX:
10695 case ISD::VECREDUCE_UMIN:
10696 case ISD::VECREDUCE_UMAX:
10697 case ISD::VECREDUCE_SMIN:
10698 case ISD::VECREDUCE_SMAX:
10700 case ISD::ATOMIC_LOAD:
10702 case ISD::FSINCOS:
return LowerFSINCOS(
Op, DAG);
10705 case ISD::DYNAMIC_STACKALLOC:
10706 if (Subtarget->isTargetWindows())
10707 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10712 case ISD::FP_EXTEND:
return LowerFP_EXTEND(
Op, DAG);
10716 return LowerSPONENTRY(
Op, DAG);
10717 case ISD::FP_TO_BF16:
10718 return LowerFP_TO_BF16(
Op, DAG);
10722 return LowerCMP(
Op, DAG);
10724 return LowerABS(
Op, DAG);
10730 unsigned IntNo =
N->getConstantOperandVal(0);
10732 if (IntNo == Intrinsic::arm_smlald)
10734 else if (IntNo == Intrinsic::arm_smlaldx)
10736 else if (IntNo == Intrinsic::arm_smlsld)
10738 else if (IntNo == Intrinsic::arm_smlsldx)
10745 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10749 N->getOperand(1),
N->getOperand(2),
10761 switch (
N->getOpcode()) {
10768 Res = ExpandBITCAST(
N, DAG, Subtarget);
10777 Res = LowerREM(
N, DAG);
10781 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10792 case ISD::READCYCLECOUNTER:
10797 assert(Subtarget->isTargetWindows() &&
"can only expand DIV on Windows");
10800 case ISD::ATOMIC_CMP_SWAP:
10835 "ROPI/RWPI not currently supported with SjLj");
10844 bool isThumb = Subtarget->isThumb();
10845 bool isThumb2 = Subtarget->
isThumb2();
10848 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10854 : &ARM::GPRRegClass;
10872 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10878 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10884 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10902 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10907 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10912 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10917 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10923 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10938 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10944 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10960 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10967 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10968 : &ARM::GPRnopcRegClass;
10972 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10973 unsigned MaxCSNum = 0;
10974 for (MachineBasicBlock &BB : *MF) {
10980 for (MachineInstr &
II : BB) {
10981 if (!
II.isEHLabel())
10984 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10985 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10987 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10988 for (
unsigned Idx : CallSiteIdxs) {
10989 CallSiteNumToLPad[Idx].push_back(&BB);
10990 MaxCSNum = std::max(MaxCSNum, Idx);
10997 std::vector<MachineBasicBlock*> LPadList;
10998 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10999 LPadList.reserve(CallSiteNumToLPad.
size());
11000 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
11001 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
11002 for (MachineBasicBlock *
MBB : MBBList) {
11003 LPadList.push_back(
MBB);
11008 assert(!LPadList.empty() &&
11009 "No landing pad destinations for the dispatch jump table!");
11012 MachineJumpTableInfo *JTI =
11019 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
11022 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
11024 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
11027 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
11031 MF->insert(MF->end(), DispatchBB);
11032 MF->insert(MF->end(), DispContBB);
11033 MF->insert(MF->end(), TrapBB);
11037 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11039 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
11043 MachineInstrBuilder MIB;
11044 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11046 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
11056 unsigned NumLPads = LPadList.size();
11057 if (Subtarget->isThumb2()) {
11058 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11059 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11065 if (NumLPads < 256) {
11066 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11068 .
addImm(LPadList.size())
11071 Register VReg1 =
MRI->createVirtualRegister(TRC);
11072 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11073 .
addImm(NumLPads & 0xFFFF)
11076 unsigned VReg2 = VReg1;
11077 if ((NumLPads & 0xFFFF0000) != 0) {
11078 VReg2 =
MRI->createVirtualRegister(TRC);
11079 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11085 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11091 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11096 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11097 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11101 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11102 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11109 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11113 }
else if (Subtarget->isThumb()) {
11114 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11115 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11121 if (NumLPads < 256) {
11122 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11127 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11132 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11133 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11135 Register VReg1 =
MRI->createVirtualRegister(TRC);
11136 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11140 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11146 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11151 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
11152 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11158 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11159 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11163 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11164 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11170 MachineMemOperand *JTMMOLd =
11174 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11175 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11181 unsigned NewVReg6 = NewVReg5;
11182 if (IsPositionIndependent) {
11183 NewVReg6 =
MRI->createVirtualRegister(TRC);
11184 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11191 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11195 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11196 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11202 if (NumLPads < 256) {
11203 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11207 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11208 Register VReg1 =
MRI->createVirtualRegister(TRC);
11209 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11210 .
addImm(NumLPads & 0xFFFF)
11213 unsigned VReg2 = VReg1;
11214 if ((NumLPads & 0xFFFF0000) != 0) {
11215 VReg2 =
MRI->createVirtualRegister(TRC);
11216 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11222 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11227 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11232 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11233 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11235 Register VReg1 =
MRI->createVirtualRegister(TRC);
11236 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11241 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11252 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11253 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11258 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11259 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11263 MachineMemOperand *JTMMOLd =
11266 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11267 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11274 if (IsPositionIndependent) {
11275 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11280 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11287 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11288 for (MachineBasicBlock *CurMBB : LPadList) {
11289 if (SeenMBBs.
insert(CurMBB).second)
11296 for (MachineBasicBlock *BB : InvokeBBs) {
11300 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11301 while (!Successors.empty()) {
11302 MachineBasicBlock *SMBB = Successors.pop_back_val();
11304 BB->removeSuccessor(SMBB);
11310 BB->normalizeSuccProbs();
11317 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11318 if (!
II->isCall())
continue;
11320 DenseSet<unsigned> DefRegs;
11322 OI =
II->operands_begin(), OE =
II->operands_end();
11324 if (!OI->isReg())
continue;
11325 DefRegs.
insert(OI->getReg());
11328 MachineInstrBuilder MIB(*MF, &*
II);
11330 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11331 unsigned Reg = SavedRegs[i];
11332 if (Subtarget->isThumb2() &&
11333 !ARM::tGPRRegClass.contains(
Reg) &&
11334 !ARM::hGPRRegClass.contains(
Reg))
11336 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11338 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11350 for (MachineBasicBlock *MBBLPad : MBBLPads)
11351 MBBLPad->setIsEHPad(
false);
11354 MI.eraseFromParent();
11367static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11369 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11370 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11372 return LdSize == 4 ? ARM::tLDRi
11373 : LdSize == 2 ? ARM::tLDRHi
11374 : LdSize == 1 ? ARM::tLDRBi : 0;
11376 return LdSize == 4 ? ARM::t2LDR_POST
11377 : LdSize == 2 ? ARM::t2LDRH_POST
11378 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11379 return LdSize == 4 ? ARM::LDR_POST_IMM
11380 : LdSize == 2 ? ARM::LDRH_POST
11381 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11386static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11388 return StSize == 16 ? ARM::VST1q32wb_fixed
11389 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11391 return StSize == 4 ? ARM::tSTRi
11392 : StSize == 2 ? ARM::tSTRHi
11393 : StSize == 1 ? ARM::tSTRBi : 0;
11395 return StSize == 4 ? ARM::t2STR_POST
11396 : StSize == 2 ? ARM::t2STRH_POST
11397 : StSize == 1 ? ARM::t2STRB_POST : 0;
11398 return StSize == 4 ? ARM::STR_POST_IMM
11399 : StSize == 2 ? ARM::STRH_POST
11400 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11407 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11408 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11409 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11410 assert(LdOpc != 0 &&
"Should have a load opcode");
11417 }
else if (IsThumb1) {
11423 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11428 }
else if (IsThumb2) {
11448 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11449 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11450 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11451 assert(StOpc != 0 &&
"Should have a store opcode");
11453 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11458 }
else if (IsThumb1) {
11465 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11470 }
else if (IsThumb2) {
11471 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11477 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11492 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11498 unsigned SizeVal =
MI.getOperand(2).getImm();
11499 unsigned Alignment =
MI.getOperand(3).getImm();
11504 unsigned UnitSize = 0;
11505 const TargetRegisterClass *TRC =
nullptr;
11506 const TargetRegisterClass *VecTRC =
nullptr;
11508 bool IsThumb1 = Subtarget->isThumb1Only();
11509 bool IsThumb2 = Subtarget->isThumb2();
11510 bool IsThumb = Subtarget->isThumb();
11512 if (Alignment & 1) {
11514 }
else if (Alignment & 2) {
11519 Subtarget->hasNEON()) {
11520 if ((Alignment % 16 == 0) && SizeVal >= 16)
11522 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11531 bool IsNeon = UnitSize >= 8;
11532 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11534 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11535 : UnitSize == 8 ? &ARM::DPRRegClass
11538 unsigned BytesLeft = SizeVal % UnitSize;
11539 unsigned LoopSize = SizeVal - BytesLeft;
11541 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11545 unsigned srcIn = src;
11546 unsigned destIn = dest;
11547 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11548 Register srcOut =
MRI.createVirtualRegister(TRC);
11549 Register destOut =
MRI.createVirtualRegister(TRC);
11550 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11552 IsThumb1, IsThumb2);
11554 IsThumb1, IsThumb2);
11562 for (
unsigned i = 0; i < BytesLeft; i++) {
11563 Register srcOut =
MRI.createVirtualRegister(TRC);
11564 Register destOut =
MRI.createVirtualRegister(TRC);
11565 Register scratch =
MRI.createVirtualRegister(TRC);
11567 IsThumb1, IsThumb2);
11569 IsThumb1, IsThumb2);
11573 MI.eraseFromParent();
11599 MF->
insert(It, loopMBB);
11600 MF->
insert(It, exitMBB);
11603 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11613 Register varEnd =
MRI.createVirtualRegister(TRC);
11614 if (Subtarget->useMovt()) {
11615 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11618 }
else if (Subtarget->genExecuteOnly()) {
11619 assert(IsThumb &&
"Non-thumb expected to have used movt");
11628 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11629 MachineMemOperand *CPMMO =
11653 MachineBasicBlock *entryBB = BB;
11655 Register varLoop =
MRI.createVirtualRegister(TRC);
11656 Register varPhi =
MRI.createVirtualRegister(TRC);
11657 Register srcLoop =
MRI.createVirtualRegister(TRC);
11658 Register srcPhi =
MRI.createVirtualRegister(TRC);
11659 Register destLoop =
MRI.createVirtualRegister(TRC);
11660 Register destPhi =
MRI.createVirtualRegister(TRC);
11668 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11674 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11676 IsThumb1, IsThumb2);
11678 IsThumb1, IsThumb2);
11682 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11688 MachineInstrBuilder MIB =
11690 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11699 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11708 auto StartOfExit = exitMBB->
begin();
11712 unsigned srcIn = srcLoop;
11713 unsigned destIn = destLoop;
11714 for (
unsigned i = 0; i < BytesLeft; i++) {
11715 Register srcOut =
MRI.createVirtualRegister(TRC);
11716 Register destOut =
MRI.createVirtualRegister(TRC);
11717 Register scratch =
MRI.createVirtualRegister(TRC);
11718 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11719 IsThumb1, IsThumb2);
11720 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11721 IsThumb1, IsThumb2);
11726 MI.eraseFromParent();
11734 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11737 assert(Subtarget->isTargetWindows() &&
11738 "__chkstk is only supported on Windows");
11739 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11759 switch (TM.getCodeModel()) {
11801 MI.eraseFromParent();
11810 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11825 .
addReg(
MI.getOperand(0).getReg())
11833 MI.eraseFromParent();
11857 if (miI == BB->
end()) {
11859 if (Succ->isLiveIn(ARM::CPSR))
11865 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11877 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11878 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11884 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11885 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11891 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11892 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11895 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11896 .
addUse(TotalIterationsReg)
11903 return TotalIterationsReg;
11914 Register TotalIterationsReg,
bool IsMemcpy) {
11921 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11922 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11923 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11931 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11932 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11933 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11940 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11941 Register RemainingLoopIterationsReg =
11942 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11943 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11944 .
addUse(TotalIterationsReg)
11946 .
addUse(RemainingLoopIterationsReg)
11950 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11951 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11952 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11953 .
addUse(ElementCountReg)
11955 .
addUse(RemainingElementsReg)
11959 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11960 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11961 .
addUse(PredCounterPhiReg)
11966 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11967 .
addUse(PredCounterPhiReg)
11975 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11976 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11985 SrcValueReg = OpSrcReg;
11987 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11998 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11999 .
addUse(LoopCounterPhiReg)
12002 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
12003 .
addUse(RemainingLoopIterationsReg)
12016 bool isThumb2 = Subtarget->isThumb2();
12017 switch (
MI.getOpcode()) {
12024 case ARM::tLDR_postidx: {
12028 .
add(
MI.getOperand(2))
12029 .
add(
MI.getOperand(3))
12030 .
add(
MI.getOperand(4))
12031 .
add(
MI.getOperand(0))
12033 MI.eraseFromParent();
12037 case ARM::MVE_MEMCPYLOOPINST:
12038 case ARM::MVE_MEMSETLOOPINST: {
12068 Register OpDestReg =
MI.getOperand(0).getReg();
12069 Register OpSrcReg =
MI.getOperand(1).getReg();
12070 Register OpSizeReg =
MI.getOperand(2).getReg();
12090 if (TpExit == BB) {
12092 "block containing memcpy/memset Pseudo");
12105 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12107 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12110 Properties.resetNoPHIs();
12122 MI.eraseFromParent();
12132 case ARM::t2STR_preidx:
12133 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12135 case ARM::t2STRB_preidx:
12136 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12138 case ARM::t2STRH_preidx:
12139 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12142 case ARM::STRi_preidx:
12143 case ARM::STRBi_preidx: {
12144 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12145 : ARM::STRB_PRE_IMM;
12147 unsigned Offset =
MI.getOperand(4).getImm();
12155 .
add(
MI.getOperand(0))
12156 .
add(
MI.getOperand(1))
12157 .
add(
MI.getOperand(2))
12159 .
add(
MI.getOperand(5))
12160 .
add(
MI.getOperand(6))
12162 MI.eraseFromParent();
12165 case ARM::STRr_preidx:
12166 case ARM::STRBr_preidx:
12167 case ARM::STRH_preidx: {
12169 switch (
MI.getOpcode()) {
12171 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12172 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12173 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12178 MI.eraseFromParent();
12182 case ARM::tMOVCCr_pseudo: {
12200 F->insert(It, copy0MBB);
12201 F->insert(It, sinkMBB);
12204 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12210 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12226 .
addImm(
MI.getOperand(3).getImm())
12227 .
addReg(
MI.getOperand(4).getReg());
12242 .
addReg(
MI.getOperand(1).getReg())
12244 .
addReg(
MI.getOperand(2).getReg())
12247 MI.eraseFromParent();
12252 case ARM::BCCZi64: {
12258 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12263 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12267 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12273 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12277 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12287 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12296 MI.eraseFromParent();
12300 case ARM::Int_eh_sjlj_setjmp:
12301 case ARM::Int_eh_sjlj_setjmp_nofp:
12302 case ARM::tInt_eh_sjlj_setjmp:
12303 case ARM::t2Int_eh_sjlj_setjmp:
12304 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12307 case ARM::Int_eh_sjlj_setup_dispatch:
12308 EmitSjLjDispatchBlock(
MI, BB);
12310 case ARM::COPY_STRUCT_BYVAL_I32:
12312 return EmitStructByval(
MI, BB);
12313 case ARM::WIN__CHKSTK:
12314 return EmitLowered__chkstk(
MI, BB);
12315 case ARM::WIN__DBZCHK:
12316 return EmitLowered__dbzchk(
MI, BB);
12332 if (!
Node->hasAnyUseOfValue(0)) {
12333 MI.getOperand(0).setIsDead(
true);
12335 if (!
Node->hasAnyUseOfValue(1)) {
12336 MI.getOperand(1).setIsDead(
true);
12340 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12341 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12342 : &ARM::GPRRegClass);
12349 if (
MI.getOpcode() == ARM::MEMCPY) {
12370 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12371 &&
"converted opcode should be the same except for cc_out"
12372 " (and, on Thumb1, pred)");
12380 if (Subtarget->isThumb1Only()) {
12381 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12382 MI.addOperand(
MI.getOperand(1));
12383 MI.removeOperand(1);
12387 for (
unsigned i =
MI.getNumOperands(); i--;) {
12389 if (
op.isReg() &&
op.isUse()) {
12392 MI.tieOperands(DefIdx, i);
12400 ccOutIdx =
MCID->getNumOperands() - 1;
12402 ccOutIdx =
MCID->getNumOperands() - 1;
12406 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12407 assert(!NewOpc &&
"Optional cc_out operand required");
12412 bool definesCPSR =
false;
12413 bool deadCPSR =
false;
12414 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12418 definesCPSR =
true;
12421 MI.removeOperand(i);
12425 if (!definesCPSR) {
12426 assert(!NewOpc &&
"Optional cc_out operand required");
12429 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12431 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12432 "expect uninitialized optional cc_out operand");
12434 if (!Subtarget->isThumb1Only())
12470 switch (
N->getOpcode()) {
12471 default:
return false;
12473 CC =
N->getOperand(0);
12495 EVT VT =
N->getValueType(0);
12496 CC =
N->getOperand(0);
12543 EVT VT =
N->getValueType(0);
12546 bool SwapSelectOps;
12548 NonConstantVal, DAG))
12554 OtherOp, NonConstantVal);
12560 CCOp, TrueVal, FalseVal);
12584 if (
N->getOpcode() ==
ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12599 if (!
N->getValueType(0).is64BitVector())
12607 EVT VT =
N->getValueType(0);
12646 EVT VT =
N->getValueType(0);
12652 Opcode = Intrinsic::arm_neon_vpaddls;
12654 Opcode = Intrinsic::arm_neon_vpaddlu;
12682 EVT VT =
N->getValueType(0);
12697 unsigned nextIndex = 0;
12748 Ops.push_back(Vec);
12765 return DAG.
getNode(ExtOp, dl, VT, tmp);
12796 if (SRA.getOpcode() !=
ISD::SRA) {
12803 if (Const->getZExtValue() != 31)
12808 if (SRA.getOperand(0) !=
Mul)
12812 SDLoc dl(AddcNode);
12813 unsigned Opcode = 0;
12819 Op0 =
Mul.getOperand(0);
12820 Op1 =
Mul.getOperand(1);
12823 Op0 =
Mul.getOperand(0);
12824 Op1 =
Mul.getOperand(1).getOperand(0);
12827 Op0 =
Mul.getOperand(0).getOperand(0);
12828 Op1 =
Mul.getOperand(1);
12831 Op0 =
Mul->getOperand(0).getOperand(0);
12832 Op1 =
Mul->getOperand(1).getOperand(0);
12841 SDValue HiMLALResult(SMLAL.getNode(), 1);
12842 SDValue LoMLALResult(SMLAL.getNode(), 0);
12848 SDValue resNode(AddcNode, 0);
12877 "Expect an ADDE or SUBE");
12881 "ADDE node has the wrong inputs");
12900 "Expect ADDC with two result values. First: i32");
12920 bool IsLeftOperandMUL =
false;
12925 IsLeftOperandMUL =
true;
12936 SDValue *LowAddSub =
nullptr;
12939 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12942 if (IsLeftOperandMUL)
12943 HiAddSub = &AddeSubeOp1;
12945 HiAddSub = &AddeSubeOp0;
12950 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12951 LoMul = &AddcSubcOp0;
12952 LowAddSub = &AddcSubcOp1;
12954 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12955 LoMul = &AddcSubcOp1;
12956 LowAddSub = &AddcSubcOp0;
12964 if (AddcSubcNode == HiAddSub->getNode() ||
12980 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12985 Ops.push_back(*HiAddSub);
12994 return SDValue(AddeSubeNode, 0);
13001 Ops.push_back(*LowAddSub);
13002 Ops.push_back(*HiAddSub);
13015 return SDValue(AddeSubeNode, 0);
13027 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13036 SDNode *UmlalNode =
nullptr;
13075 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13080 SDNode* AddcNode =
N->getOperand(2).getNode();
13081 SDNode* AddeNode =
N->getOperand(3).getNode();
13089 {N->getOperand(0), N->getOperand(1),
13090 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13114 int32_t imm =
C->getSExtValue();
13115 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13120 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13135 int64_t imm =
C->getSExtValue();
13146 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13147 N->getOperand(0),
RHS,
N->getOperand(2));
13159 if (!Subtarget->hasMVEIntegerOps())
13172 SetCC =
N->getOperand(0);
13176 TrueVal =
N->getOperand(1);
13177 FalseVal =
N->getOperand(2);
13179 LHS =
N->getOperand(0);
13180 RHS =
N->getOperand(1);
13182 TrueVal =
N->getOperand(2);
13183 FalseVal =
N->getOperand(3);
13188 unsigned int Opcode = 0;
13189 if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMIN ||
13190 FalseVal->getOpcode() == ISD::VECREDUCE_UMIN) &&
13195 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMIN ||
13196 FalseVal->getOpcode() == ISD::VECREDUCE_SMIN) &&
13201 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMAX ||
13202 FalseVal->getOpcode() == ISD::VECREDUCE_UMAX) &&
13207 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMAX ||
13208 FalseVal->getOpcode() == ISD::VECREDUCE_SMAX) &&
13217 switch (TrueVal->getOpcode()) {
13218 case ISD::VECREDUCE_UMIN:
13219 case ISD::VECREDUCE_SMIN:
13220 case ISD::VECREDUCE_UMAX:
13221 case ISD::VECREDUCE_SMAX:
13236 if (TrueVal !=
LHS || FalseVal !=
RHS)
13239 EVT LeftType =
LHS->getValueType(0);
13240 EVT RightType =
RHS->getValueType(0);
13243 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13247 if (VectorScalarType != MVT::i32)
13255 if (VectorScalarType != MVT::i32)
13268 EVT VT =
N->getValueType(0);
13276 Shft =
N->getOperand(0);
13283 Cmp.getOperand(0) !=
N->getOperand(1) ||
13284 Cmp.getOperand(1) !=
N->getOperand(2))
13286 Shft =
N->getOperand(1);
13298 ScalarType = MVT::i8;
13301 case (1 << 15) - 1:
13302 ScalarType = MVT::i16;
13305 case (1ULL << 31) - 1:
13306 ScalarType = MVT::i32;
13337 unsigned LegalLanes = 128 / (ShftAmt + 1);
13361 for (
unsigned I = 0;
I < NumParts; ++
I) {
13378 if (!Subtarget->hasMVEIntegerOps())
13393 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13403 if (!Const || !Const->isOne())
13421 EVT VT =
N->getValueType(0);
13423 if (!Subtarget->hasMVEIntegerOps() ||
13452 Opc = Intrinsic::arm_mve_vctp64;
13455 Opc = Intrinsic::arm_mve_vctp32;
13458 Opc = Intrinsic::arm_mve_vctp16;
13461 Opc = Intrinsic::arm_mve_vctp8;
13515 EVT VT =
N->getValueType(0);
13521 switch (
Op.getOpcode()) {
13522 case ISD::VECREDUCE_ADD:
13546 unsigned N0RedOp = 0;
13553 unsigned N1RedOp = 0;
13567 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13569 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13576 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13600 if (!BaseLocDecomp0.getBase() ||
13601 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13602 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13604 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13606 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13616 if (IsBefore < 0) {
13619 }
else if (IsBefore > 0) {
13632 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13642 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13652 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13654 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13661 if (!Subtarget->hasMVEIntegerOps())
13667 EVT VT =
N->getValueType(0);
13672 if (VT != MVT::i64)
13683 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13703 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13752 "Expected shift op");
13754 SDValue ShiftLHS =
N->getOperand(0);
13768 if (Subtarget->isThumb1Only()) {
13779 if (Const->getAPIntValue().ult(256))
13782 Const->getAPIntValue().sgt(-256))
13798 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13799 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13800 "Expected XOR(SHIFT) pattern");
13805 if (XorC && ShiftC) {
13806 unsigned MaskIdx, MaskLen;
13807 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13808 unsigned ShiftAmt = ShiftC->getZExtValue();
13809 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13810 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13811 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13812 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13822 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13824 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13825 "Expected shift-shift mask");
13827 if (!Subtarget->isThumb1Only())
13837 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13839 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13844 if (!Subtarget->hasNEON()) {
13845 if (Subtarget->isThumb1Only())
13859 return Subtarget->hasVFP2Base();
13861 return Subtarget->hasVFP2Base();
13863 return Subtarget->hasFP64();
13866 return Subtarget->hasMVEFloatOps();
13895 if (ST->isThumb() && ST->isThumb1Only())
13899 for (
auto *U :
N->users()) {
13900 switch(U->getOpcode()) {
13918 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13919 U->getOperand(1).getOpcode() ==
ISD::SHL)
13929 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13936 if (!C1ShlC2 || !C2)
13939 APInt C2Int = C2->getAPIntValue();
13940 APInt C1Int = C1ShlC2->getAPIntValue();
13942 if (C2Int.
uge(C2Width))
13948 if ((C1Int & Mask) != C1Int)
13955 auto LargeImm = [](
const APInt &Imm) {
13956 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13957 return Imm.getBitWidth() - Zeros > 8;
13960 if (LargeImm(C1Int) || LargeImm(C2Int))
13972 SHL.dump();
N->dump());
14007 if (CSINC.getOpcode() !=
ARMISD::CSINC || !CSINC.hasOneUse())
14016 CSINC.getOperand(0)),
14017 CSINC.getOperand(1), CSINC.getOperand(2),
14018 CSINC.getOperand(3));
14075 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14117 if (!Subtarget->hasVMLxForwarding())
14136 EVT VT =
N->getValueType(0);
14147 EVT VT =
N->getValueType(0);
14148 if (VT != MVT::v2i64)
14159 return Op->getOperand(0);
14172 if (
And->getOpcode() == ISD::BITCAST)
14173 And =
And->getOperand(0);
14177 if (Mask->getOpcode() == ISD::BITCAST)
14178 Mask = Mask->getOperand(0);
14181 Mask.getValueType() != MVT::v4i32)
14187 return And->getOperand(0);
14192 if (
SDValue Op0 = IsSignExt(N0)) {
14193 if (
SDValue Op1 = IsSignExt(N1)) {
14199 if (
SDValue Op0 = IsZeroExt(N0)) {
14200 if (
SDValue Op1 = IsZeroExt(N1)) {
14215 EVT VT =
N->getValueType(0);
14216 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14227 if (VT != MVT::i32)
14234 int64_t MulAmt =
C->getSExtValue();
14237 ShiftAmt = ShiftAmt & (32 - 1);
14242 MulAmt >>= ShiftAmt;
14303 if (
N->getValueType(0) != MVT::i32)
14312 if (C1 == 255 || C1 == 65535)
14315 SDNode *N0 =
N->getOperand(0).getNode();
14329 if (!C2 || C2 >= 32)
14373 if (Trailing == C2 && C2 + C3 < 32) {
14386 if (Leading == C2 && C2 + C3 < 32) {
14414 EVT VT =
N->getValueType(0);
14418 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14421 APInt SplatBits, SplatUndef;
14422 unsigned SplatBitSize;
14424 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14425 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14426 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14427 SplatBitSize == 64) {
14461 if (!Subtarget->hasV6Ops() ||
14462 (Subtarget->isThumb() &&
14463 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14466 SDValue SRL = OR->getOperand(0);
14467 SDValue SHL = OR->getOperand(1);
14470 SRL = OR->getOperand(1);
14471 SHL = OR->getOperand(0);
14478 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14482 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14483 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14484 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14503 unsigned Opcode = 0;
14504 if (
isS16(OpS16, DAG))
14522 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14525 EVT VT =
N->getValueType(0);
14540 if (VT != MVT::i32)
14553 if (Mask == 0xffff)
14560 if ((Val & ~Mask) != Val)
14585 (Mask == ~Mask2)) {
14588 if (Subtarget->hasDSP() &&
14589 (Mask == 0xffff || Mask == 0xffff0000))
14602 (~Mask == Mask2)) {
14605 if (Subtarget->hasDSP() &&
14606 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14672 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14679 EVT VT =
N->getValueType(0);
14684 auto IsFreelyInvertable = [&](
SDValue V) {
14691 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14707 EVT VT =
N->getValueType(0);
14713 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14714 VT == MVT::v8i1 || VT == MVT::v16i1))
14717 APInt SplatBits, SplatUndef;
14718 unsigned SplatBitSize;
14720 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14721 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14722 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14723 SplatBitSize == 64) {
14759 unsigned SplatBitSize;
14762 APInt SplatBits0, SplatBits1;
14766 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14767 HasAnyUndefs) && !HasAnyUndefs) {
14768 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14769 HasAnyUndefs) && !HasAnyUndefs) {
14774 SplatBits0 == ~SplatBits1) {
14804 EVT VT =
N->getValueType(0);
14819 if (Subtarget->hasMVEIntegerOps()) {
14850 ToMask =
~N->getConstantOperandAPInt(2);
14870 unsigned LastActiveBitInA =
A.countr_zero();
14871 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14872 return LastActiveBitInA - 1 == FirstActiveBitInB;
14877 APInt ToMask, FromMask;
14885 APInt NewToMask, NewFromMask;
14887 if (NewFrom != From)
14891 if ((NewToMask & ToMask).getBoolValue())
14916 unsigned InvMask =
N->getConstantOperandVal(2);
14920 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14921 "undefined behavior");
14922 unsigned Mask = (1u << Width) - 1;
14924 if ((Mask & (~Mask2)) == 0)
14926 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14933 APInt ToMask1, FromMask1;
14936 APInt ToMask2, FromMask2;
14942 APInt NewFromMask = FromMask1 | FromMask2;
14943 APInt NewToMask = ToMask1 | ToMask2;
14945 EVT VT =
N->getValueType(0);
14948 if (NewFromMask[0] == 0)
14960 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14961 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14963 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14967 EVT VT =
N->getValueType(0);
14970 N->getOperand(1),
N->getOperand(2));
14984 SDValue CSInc = Cmp->getOperand(0);
15034 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15035 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15038 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15040 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15053 SDValue InDouble =
N->getOperand(0);
15068 SDValue BasePtr = LD->getBasePtr();
15070 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15071 LD->getAlign(), LD->getMemOperand()->getFlags());
15077 LD->getPointerInfo().getWithOffset(4),
15079 LD->getMemOperand()->getFlags());
15095 bool BVSwap = BV.
getOpcode() == ISD::BITCAST;
15100 BVSwap = BV.
getOpcode() == ISD::BITCAST;
15112 if (!Subtarget->
isLittle() && BVSwap)
15130 if (!Subtarget->
isLittle() && BVSwap)
15173 if (Op0->
getOpcode() == ISD::BITCAST) {
15175 if (Copy.getValueType() == MVT::f32 &&
15177 bool HasGlue = Copy->getNumOperands() == 3;
15178 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15179 HasGlue ? Copy->getOperand(2) :
SDValue()};
15180 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15199 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15200 LN0->getMemoryVT() == MVT::i16) {
15203 LN0->getBasePtr(), LN0->getMemOperand());
15221 EVT VT =
N->getValueType(0);
15255 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15256 for (
unsigned i = 0; i < NumElts; ++i) {
15257 SDNode *Elt =
N->getOperand(i).getNode();
15274 if (
N->getNumOperands() == 2)
15280 EVT VT =
N->getValueType(0);
15286 for (
unsigned i = 0; i < NumElts; ++i) {
15287 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(i));
15294 return DAG.
getNode(ISD::BITCAST, dl, VT, BV);
15312 EVT VT =
N->getValueType(0);
15320 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15324 if (
Use->getOpcode() != ISD::BITCAST ||
15325 Use->getValueType(0).isFloatingPoint())
15333 unsigned NumOfBitCastedElts = 0;
15335 unsigned NumOfRelevantElts = NumElts;
15336 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15338 if (Elt->
getOpcode() == ISD::BITCAST) {
15341 ++NumOfBitCastedElts;
15345 --NumOfRelevantElts;
15349 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15367 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15371 if (V.getOpcode() == ISD::BITCAST &&
15372 V->getOperand(0).getValueType() == MVT::i32)
15374 V = V.getOperand(0);
15383 Vec = DAG.
getNode(ISD::BITCAST, dl, VT, Vec);
15391 EVT VT =
N->getValueType(0);
15398 if (
Op->getOperand(0).getValueType() == VT)
15399 return Op->getOperand(0);
15414 if (
Op.getValueType() == MVT::i32) {
15425 EVT VT =
N->getValueType(0);
15430 if (ST->isLittle())
15431 return DAG.
getNode(ISD::BITCAST, dl, VT,
Op);
15434 if (
Op.getValueType() == VT)
15443 if (
Op->getOperand(0).getValueType() == VT)
15444 return Op->getOperand(0);
15453 if (!Subtarget->hasMVEIntegerOps())
15456 EVT VT =
N->getValueType(0);
15487 EVT VT =
N->getValueType(0);
15488 SDNode *Elt =
N->getOperand(1).getNode();
15497 SDValue Vec = DAG.
getNode(ISD::BITCAST, dl, FloatVT,
N->getOperand(0));
15498 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(1));
15503 Vec, V,
N->getOperand(2));
15504 return DAG.
getNode(ISD::BITCAST, dl, VT, InsElt);
15513 EVT VT =
N->getValueType(0);
15521 if (Ext.getOpcode() == ISD::BITCAST &&
15522 Ext.getOperand(0).getValueType() == MVT::f32)
15523 Ext = Ext.getOperand(0);
15526 Ext.getConstantOperandVal(1) % 2 != 0)
15528 if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() ==
ISD::SINT_TO_FP ||
15532 SDValue Op0 = Ext.getOperand(0);
15535 unsigned Lane = Ext.getConstantOperandVal(1);
15541 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15542 isa<ConstantSDNode>(V->getOperand(1)) &&
15543 V->getConstantOperandVal(1) == Lane + 1 &&
15544 V->getOperand(0).getResNo() == ResNo;
15546 if (OtherIt == Op0->
users().
end())
15551 SDValue OtherExt(*OtherIt, 0);
15564 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15576 EVT VT =
N->getValueType(0);
15582 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15584 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15586 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15589 while (
X.getValueType() != VT &&
X->getOpcode() == ISD::BITCAST)
15590 X =
X->getOperand(0);
15591 if (
X.getValueType() == VT)
15599 return Op0.
getOperand(
N->getConstantOperandVal(1));
15609 unsigned Offset =
N->getConstantOperandVal(1);
15621 unsigned Idx =
N->getConstantOperandVal(1);
15635 EVT VT =
N->getValueType(0);
15640 Op.getOperand(0).getValueType().getScalarType())
15650 SDValue SubVec =
N->getOperand(1);
15651 uint64_t IdxVal =
N->getConstantOperandVal(2);
15662 if (IdxVal == 0 && Vec.
isUndef())
15668 (IdxVal != 0 && IdxVal != NumSubElts))
15741 EVT VT =
N->getValueType(0);
15752 unsigned HalfElts = NumElts/2;
15754 for (
unsigned n = 0; n < NumElts; ++n) {
15757 if (MaskElt < (
int)HalfElts)
15759 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15760 NewElt = HalfElts + MaskElt - NumElts;
15803 bool SimpleConstIncOnly,
15811 bool isLoadOp =
true;
15812 bool isLaneOp =
false;
15815 bool hasAlignment =
true;
15816 unsigned NewOpc = 0;
15817 unsigned NumVecs = 0;
15818 if (
Target.isIntrinsic) {
15819 unsigned IntNo =
N->getConstantOperandVal(1);
15823 case Intrinsic::arm_neon_vld1:
15827 case Intrinsic::arm_neon_vld2:
15831 case Intrinsic::arm_neon_vld3:
15835 case Intrinsic::arm_neon_vld4:
15839 case Intrinsic::arm_neon_vld1x2:
15842 hasAlignment =
false;
15844 case Intrinsic::arm_neon_vld1x3:
15847 hasAlignment =
false;
15849 case Intrinsic::arm_neon_vld1x4:
15852 hasAlignment =
false;
15854 case Intrinsic::arm_neon_vld2dup:
15858 case Intrinsic::arm_neon_vld3dup:
15862 case Intrinsic::arm_neon_vld4dup:
15866 case Intrinsic::arm_neon_vld2lane:
15871 case Intrinsic::arm_neon_vld3lane:
15876 case Intrinsic::arm_neon_vld4lane:
15881 case Intrinsic::arm_neon_vst1:
15886 case Intrinsic::arm_neon_vst2:
15891 case Intrinsic::arm_neon_vst3:
15896 case Intrinsic::arm_neon_vst4:
15901 case Intrinsic::arm_neon_vst2lane:
15907 case Intrinsic::arm_neon_vst3lane:
15913 case Intrinsic::arm_neon_vst4lane:
15919 case Intrinsic::arm_neon_vst1x2:
15923 hasAlignment =
false;
15925 case Intrinsic::arm_neon_vst1x3:
15929 hasAlignment =
false;
15931 case Intrinsic::arm_neon_vst1x4:
15935 hasAlignment =
false;
15940 switch (
N->getOpcode()) {
15976 VecTy =
N->getValueType(0);
15977 }
else if (
Target.isIntrinsic) {
15978 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
15981 "Node has to be a load, a store, or an intrinsic!");
15982 VecTy =
N->getOperand(1).getValueType();
15990 if (isLaneOp || isVLDDUPOp)
15993 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
15999 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16008 EVT AlignedVecTy = VecTy;
16028 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16029 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16040 Alignment =
Align(1);
16046 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16048 for (n = 0; n < NumResultVecs; ++n)
16049 Tys[n] = AlignedVecTy;
16050 Tys[n++] = MVT::i32;
16051 Tys[n] = MVT::Other;
16056 Ops.push_back(
N->getOperand(0));
16057 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16062 Ops.push_back(StN->getValue());
16066 unsigned LastOperand =
16067 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16068 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16069 Ops.push_back(
N->getOperand(i));
16077 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::STORE) {
16079 StVal = DAG.
getNode(ISD::BITCAST, dl, AlignedVecTy, StVal);
16088 for (
unsigned i = 0; i < NumResultVecs; ++i)
16093 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::LOAD) {
16094 SDValue &LdVal = NewResults[0];
16095 LdVal = DAG.
getNode(ISD::BITCAST, dl, VecTy, LdVal);
16130 switch (
N->getOpcode()) {
16134 *
Ptr =
N->getOperand(0);
16135 *CInc =
N->getOperand(1);
16142 *
Ptr =
N->getOperand(1);
16143 *CInc =
N->getOperand(2);
16162 const bool isStore =
N->getOpcode() == ISD::STORE;
16170 SDValue Addr =
N->getOperand(AddrOpIdx);
16181 unsigned ConstInc =
16186 if (BaseUpdates.
size() >= MaxBaseUpdates)
16206 unsigned UserOffset =
16209 if (!UserOffset || UserOffset <=
Offset)
16212 unsigned NewConstInc = UserOffset -
Offset;
16215 if (BaseUpdates.
size() >= MaxBaseUpdates)
16222 unsigned NumValidUpd = BaseUpdates.
size();
16223 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16234 return LHS.ConstInc <
RHS.ConstInc;
16263 unsigned IntNo =
N->getConstantOperandVal(1);
16264 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16266 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16289 bool isLoadOp =
true;
16290 unsigned NewOpc = 0;
16291 unsigned NumVecs = 0;
16295 case Intrinsic::arm_mve_vld2q:
16299 case Intrinsic::arm_mve_vld4q:
16303 case Intrinsic::arm_mve_vst2q:
16308 case Intrinsic::arm_mve_vst4q:
16318 VecTy =
N->getValueType(0);
16320 VecTy =
N->getOperand(3).getValueType();
16334 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16336 for (n = 0; n < NumResultVecs; ++n)
16338 Tys[n++] = MVT::i32;
16339 Tys[n] = MVT::Other;
16344 Ops.push_back(
N->getOperand(0));
16345 Ops.push_back(
N->getOperand(2));
16346 Ops.push_back(Inc);
16348 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16349 Ops.push_back(
N->getOperand(i));
16356 for (
unsigned i = 0; i < NumResultVecs; ++i)
16375 EVT VT =
N->getValueType(0);
16381 SDNode *VLD =
N->getOperand(0).getNode();
16384 unsigned NumVecs = 0;
16385 unsigned NewOpc = 0;
16387 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16390 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16393 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16405 if (
Use.getResNo() == NumVecs)
16409 VLDLaneNo !=
User->getConstantOperandVal(1))
16416 for (n = 0; n < NumVecs; ++n)
16418 Tys[n] = MVT::Other;
16428 unsigned ResNo =
Use.getResNo();
16430 if (ResNo == NumVecs)
16437 std::vector<SDValue> VLDDupResults;
16438 for (
unsigned n = 0; n < NumVecs; ++n)
16452 EVT VT =
N->getValueType(0);
16455 if (Subtarget->hasMVEIntegerOps()) {
16459 ExtractVT = MVT::i32;
16461 N->getOperand(0),
N->getOperand(1));
16472 while (
Op.getOpcode() == ISD::BITCAST)
16473 Op =
Op.getOperand(0);
16478 unsigned EltSize =
Op.getScalarValueSizeInBits();
16480 unsigned Imm =
Op.getConstantOperandVal(0);
16496 if (Subtarget->hasMVEIntegerOps()) {
16499 if (
Op.getValueType() == MVT::f32)
16501 DAG.
getNode(ISD::BITCAST, dl, MVT::i32,
Op));
16502 else if (
Op.getValueType() == MVT::f16)
16507 if (!Subtarget->hasNEON())
16514 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16515 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16516 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16521 LD->getMemoryVT(), LD->getMemOperand());
16532 EVT VT =
N->getValueType(0);
16554 assert(StVT != VT &&
"Cannot truncate to the same type");
16564 if (0 != (NumElems * FromEltSz) % ToEltSz)
16567 unsigned SizeRatio = FromEltSz / ToEltSz;
16572 NumElems * SizeRatio);
16578 for (
unsigned i = 0; i < NumElems; ++i)
16592 MVT StoreType = MVT::i8;
16594 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16614 for (
unsigned I = 0;
I <
E;
I++) {
16645 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16648 unsigned NumElements = 4;
16665 unsigned Off0 = Rev ? NumElts : 0;
16666 unsigned Off1 = Rev ? 0 : NumElts;
16668 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16669 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16671 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16679 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16699 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16714 NewToVT, Alignment, MMOFlags, AAInfo);
16747 unsigned NewOffset =
16755 NewToVT, Alignment, MMOFlags, AAInfo);
16777 {Extract.getOperand(0), Extract.getOperand(1)});
16808 if (Subtarget->hasNEON())
16812 if (Subtarget->hasMVEFloatOps())
16816 if (Subtarget->hasMVEIntegerOps()) {
16891 if (!Subtarget->hasNEON())
16895 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16903 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16905 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16906 uint32_t IntBits = IntTy.getSizeInBits();
16907 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16908 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16919 if (
C == -1 ||
C == 0 ||
C > 32)
16924 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16925 Intrinsic::arm_neon_vcvtfp2fxu;
16928 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16931 if (IntBits < FloatBits)
16939 if (!Subtarget->hasMVEFloatOps())
16947 EVT VT =
N->getValueType(0);
16952 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16953 if (
Op.getOpcode() != ISD::BITCAST ||
16956 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16957 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16959 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16972 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
16983 EVT VT =
N->getValueType(0);
16986 if (!
N->getFlags().hasAllowReassociation())
16993 unsigned Opc =
A.getConstantOperandVal(0);
16994 if (
Opc != Intrinsic::arm_mve_vcmlaq)
16999 A.getOperand(3),
A.getOperand(4));
17031 if (!Subtarget->hasNEON())
17035 unsigned OpOpcode =
Op.getNode()->getOpcode();
17036 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17040 SDValue ConstVec =
N->getOperand(1);
17044 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17046 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17047 uint32_t IntBits = IntTy.getSizeInBits();
17048 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17049 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17069 int32_t
C = IntVal.exactLogBase2();
17070 if (
C == -1 ||
C == 0 ||
C > 32)
17076 if (IntBits < FloatBits)
17078 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17080 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17081 : Intrinsic::arm_neon_vcvtfxu2fp;
17089 if (!ST->hasMVEIntegerOps())
17092 assert(
N->getOpcode() == ISD::VECREDUCE_ADD);
17093 EVT ResVT =
N->getValueType(0);
17121 EVT AVT =
A.getValueType();
17127 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17128 EVT AVT =
A.getValueType();
17136 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17137 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17140 if (ExtTypeMatches(
A, ExtTypes))
17141 return ExtendIfNeeded(
A, ExtendCode);
17144 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17151 if (Ext->getOpcode() != ExtendCode)
17154 if (ExtTypeMatches(
A, ExtTypes))
17155 return ExtendIfNeeded(
A, ExtendCode);
17158 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17168 if (ResVT != RetTy)
17171 if (
Mul->getOpcode() == ExtendCode &&
17172 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17174 Mul =
Mul->getOperand(0);
17183 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17184 A = ExtendIfNeeded(
A, ExtendCode);
17185 B = ExtendIfNeeded(
B, ExtendCode);
17190 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17203 if (
Mul->getOpcode() == ExtendCode &&
17204 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17206 Mul =
Mul->getOperand(0);
17215 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17216 A = ExtendIfNeeded(
A, ExtendCode);
17217 B = ExtendIfNeeded(
B, ExtendCode);
17228 EVT VT =
Ops[0].getValueType();
17229 if (VT == MVT::v16i8) {
17231 "Unexpected illegal long reduction opcode");
17260 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17263 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17327 Op =
Op->getOperand(1);
17329 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17331 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17337 return DAG.
getNode(ISD::VECREDUCE_ADD, dl, ResVT, Ext);
17348 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17350 if (!Shuf || !Shuf->getOperand(1).isUndef())
17355 APInt SetElts(Mask.size(), 0);
17356 for (
int E : Mask) {
17364 if (
N->getNumOperands() != VecOp + 1) {
17366 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17372 if (
Op.getValueType().isVector())
17373 Ops.push_back(
Op.getOperand(0));
17384 unsigned IsTop =
N->getConstantOperandVal(2);
17391 if (Op0->
isUndef() && !IsTop)
17405 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17407 APInt Op0DemandedElts =
17408 IsTop ? Op1DemandedElts
17423 unsigned IsTop =
N->getConstantOperandVal(2);
17425 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17426 APInt Op0DemandedElts =
17438 EVT VT =
N->getValueType(0);
17445 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17446 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17450 LHS.getOperand(0),
RHS.getOperand(0));
17465 int ShiftAmt =
C->getSExtValue();
17466 if (ShiftAmt == 0) {
17472 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17473 unsigned NewOpcode =
17489 unsigned IntNo =
N->getConstantOperandVal(0);
17500 case Intrinsic::arm_neon_vshifts:
17501 case Intrinsic::arm_neon_vshiftu:
17502 case Intrinsic::arm_neon_vrshifts:
17503 case Intrinsic::arm_neon_vrshiftu:
17504 case Intrinsic::arm_neon_vrshiftn:
17505 case Intrinsic::arm_neon_vqshifts:
17506 case Intrinsic::arm_neon_vqshiftu:
17507 case Intrinsic::arm_neon_vqshiftsu:
17508 case Intrinsic::arm_neon_vqshiftns:
17509 case Intrinsic::arm_neon_vqshiftnu:
17510 case Intrinsic::arm_neon_vqshiftnsu:
17511 case Intrinsic::arm_neon_vqrshiftns:
17512 case Intrinsic::arm_neon_vqrshiftnu:
17513 case Intrinsic::arm_neon_vqrshiftnsu: {
17514 EVT VT =
N->getOperand(1).getValueType();
17516 unsigned VShiftOpc = 0;
17519 case Intrinsic::arm_neon_vshifts:
17520 case Intrinsic::arm_neon_vshiftu:
17525 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17532 case Intrinsic::arm_neon_vrshifts:
17533 case Intrinsic::arm_neon_vrshiftu:
17538 case Intrinsic::arm_neon_vqshifts:
17539 case Intrinsic::arm_neon_vqshiftu:
17544 case Intrinsic::arm_neon_vqshiftsu:
17549 case Intrinsic::arm_neon_vrshiftn:
17550 case Intrinsic::arm_neon_vqshiftns:
17551 case Intrinsic::arm_neon_vqshiftnu:
17552 case Intrinsic::arm_neon_vqshiftnsu:
17553 case Intrinsic::arm_neon_vqrshiftns:
17554 case Intrinsic::arm_neon_vqrshiftnu:
17555 case Intrinsic::arm_neon_vqrshiftnsu:
17567 case Intrinsic::arm_neon_vshifts:
17568 case Intrinsic::arm_neon_vshiftu:
17571 case Intrinsic::arm_neon_vrshifts:
17574 case Intrinsic::arm_neon_vrshiftu:
17577 case Intrinsic::arm_neon_vrshiftn:
17580 case Intrinsic::arm_neon_vqshifts:
17583 case Intrinsic::arm_neon_vqshiftu:
17586 case Intrinsic::arm_neon_vqshiftsu:
17589 case Intrinsic::arm_neon_vqshiftns:
17592 case Intrinsic::arm_neon_vqshiftnu:
17595 case Intrinsic::arm_neon_vqshiftnsu:
17598 case Intrinsic::arm_neon_vqrshiftns:
17601 case Intrinsic::arm_neon_vqrshiftnu:
17604 case Intrinsic::arm_neon_vqrshiftnsu:
17610 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17611 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17614 case Intrinsic::arm_neon_vshiftins: {
17615 EVT VT =
N->getOperand(1).getValueType();
17617 unsigned VShiftOpc = 0;
17621 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17628 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17629 N->getOperand(1),
N->getOperand(2),
17633 case Intrinsic::arm_neon_vqrshifts:
17634 case Intrinsic::arm_neon_vqrshiftu:
17638 case Intrinsic::arm_neon_vbsl: {
17641 N->getOperand(2),
N->getOperand(3));
17643 case Intrinsic::arm_mve_vqdmlah:
17644 case Intrinsic::arm_mve_vqdmlash:
17645 case Intrinsic::arm_mve_vqrdmlah:
17646 case Intrinsic::arm_mve_vqrdmlash:
17647 case Intrinsic::arm_mve_vmla_n_predicated:
17648 case Intrinsic::arm_mve_vmlas_n_predicated:
17649 case Intrinsic::arm_mve_vqdmlah_predicated:
17650 case Intrinsic::arm_mve_vqdmlash_predicated:
17651 case Intrinsic::arm_mve_vqrdmlah_predicated:
17652 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17657 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17664 case Intrinsic::arm_mve_minv:
17665 case Intrinsic::arm_mve_maxv:
17666 case Intrinsic::arm_mve_minav:
17667 case Intrinsic::arm_mve_maxav:
17668 case Intrinsic::arm_mve_minv_predicated:
17669 case Intrinsic::arm_mve_maxv_predicated:
17670 case Intrinsic::arm_mve_minav_predicated:
17671 case Intrinsic::arm_mve_maxav_predicated: {
17674 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17681 case Intrinsic::arm_mve_addv: {
17684 bool Unsigned =
N->getConstantOperandVal(2);
17689 case Intrinsic::arm_mve_addlv:
17690 case Intrinsic::arm_mve_addlv_predicated: {
17693 bool Unsigned =
N->getConstantOperandVal(2);
17694 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17699 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17701 Ops.push_back(
N->getOperand(i));
17722 EVT VT =
N->getValueType(0);
17724 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17725 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17726 N->getOperand(0)->hasOneUse()) {
17743 if (AndMask == 255 || AndMask == 65535)
17747 if (MaskedBits > ShiftAmt) {
17762 if (ST->hasMVEIntegerOps())
17767 switch (
N->getOpcode()) {
17780 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17781 unsigned VShiftOpc =
17784 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17800 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17803 EVT FromVT = LD->getValueType(0);
17804 EVT ToVT =
N->getValueType(0);
17811 unsigned NumElements = 0;
17812 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17814 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17816 if (NumElements == 0 ||
17826 SDValue BasePtr = LD->getBasePtr();
17827 Align Alignment = LD->getBaseAlign();
17848 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17849 Alignment, MMOFlags, AAInfo);
17855 if (FromEltVT == MVT::f16) {
17858 for (
unsigned i = 0; i < Loads.
size(); i++) {
17884 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17888 EVT VT =
N->getValueType(0);
17892 if (VT == MVT::i32 &&
17893 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17898 switch (
N->getOpcode()) {
17912 if (ST->hasMVEIntegerOps())
17921 if (ST->hasMVEFloatOps())
17932 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17936 EVT VT =
Op.getValueType();
17939 if (VT != MVT::i32 ||
17952 APInt MaxC = Max.getConstantOperandAPInt(1);
17955 !(MinC + 1).isPowerOf2())
17973 EVT VT =
N->getValueType(0);
17976 if (VT == MVT::i32)
17979 if (!ST->hasMVEIntegerOps())
17985 if (VT != MVT::v4i32 && VT != MVT::v8i16)
17988 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
17996 if (VT == MVT::v4i32)
17997 SaturateC =
APInt(32, (1 << 15) - 1,
true);
17999 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18006 MaxC != ~SaturateC)
18011 if (IsSignedSaturate(
N, N0.
getNode())) {
18014 if (VT == MVT::v4i32) {
18015 HalfVT = MVT::v8i16;
18016 ExtVT = MVT::v4i16;
18018 HalfVT = MVT::v16i8;
18033 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18039 if (VT == MVT::v4i32)
18040 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18042 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18051 if (IsUnsignedSaturate(
N)) {
18055 if (VT == MVT::v4i32) {
18056 HalfVT = MVT::v8i16;
18057 ExtConst = 0x0000FFFF;
18059 HalfVT = MVT::v16i8;
18081 const APInt *CV = &
C->getAPIntValue();
18099 SDValue Op0 = CMOV->getOperand(0);
18100 SDValue Op1 = CMOV->getOperand(1);
18101 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
18102 SDValue CmpZ = CMOV->getOperand(3);
18138 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18145 if ((OrCI & Known.
Zero) != OrCI)
18151 EVT VT =
X.getValueType();
18152 unsigned BitInX = AndC->
logBase2();
18160 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18161 BitInY < NumActiveBits; ++BitInY) {
18162 if (OrCI[BitInY] == 0)
18165 Mask.setBit(BitInY);
18182 switch (
N->getOpcode()) {
18197 if (Const->isZero())
18199 else if (Const->isOne())
18207 unsigned IntOp =
N.getConstantOperandVal(1);
18208 if (IntOp != Intrinsic::test_start_loop_iterations &&
18209 IntOp != Intrinsic::loop_decrement_reg)
18235 bool Negate =
false;
18239 if (
N->getOpcode() == ISD::BRCOND) {
18241 Cond =
N->getOperand(1);
18242 Dest =
N->getOperand(2);
18244 assert(
N->getOpcode() == ISD::BR_CC &&
"Expected BRCOND or BR_CC!");
18246 Cond =
N->getOperand(2);
18247 Dest =
N->getOperand(4);
18249 if (!Const->isOne() && !Const->isZero())
18251 Imm = Const->getZExtValue();
18279 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18280 "unsupported condition");
18285 unsigned IntOp =
Int->getConstantOperandVal(1);
18286 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() == ISD::BR) &&
18287 "expected single br user");
18288 SDNode *Br = *
N->user_begin();
18298 if (IntOp == Intrinsic::test_start_loop_iterations) {
18302 if (IsTrueIfZero(CC, Imm)) {
18308 UpdateUncondBr(Br, Dest, DAG);
18310 SDValue Ops[] = {Chain, Setup, OtherTarget};
18323 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18327 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18331 if (
Target == OtherTarget)
18332 UpdateUncondBr(Br, Dest, DAG);
18352 SDValue LHS = Cmp.getOperand(0);
18353 SDValue RHS = Cmp.getOperand(1);
18363 LHS->getOperand(0)->hasOneUse() &&
18383 EVT VT =
N->getValueType(0);
18385 SDValue LHS = Cmp.getOperand(0);
18386 SDValue RHS = Cmp.getOperand(1);
18387 SDValue FalseVal =
N->getOperand(0);
18388 SDValue TrueVal =
N->getOperand(1);
18393 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18417 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18419 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18431 LHS->getOperand(2), LHS->getOperand(3));
18441 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18445 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18447 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18456 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18521 const APInt *TrueConst;
18522 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18523 ((FalseVal.getOpcode() ==
ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18524 FalseVal.getOperand(1) == RHS) ||
18528 unsigned ShiftAmount = TrueConst->
logBase2();
18543 if (Known.
Zero == 0xfffffffe)
18546 else if (Known.
Zero == 0xffffff00)
18549 else if (Known.
Zero == 0xffff0000)
18562 EVT DstVT =
N->getValueType(0);
18565 if (ST->hasMVEIntegerOps() && Src.getOpcode() ==
ARMISD::VDUP) {
18566 EVT SrcVT = Src.getValueType();
18574 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18575 Src.getValueType().getScalarSizeInBits())
18576 Src = Src.getOperand(0);
18580 EVT SrcVT = Src.getValueType();
18600 EVT VT =
N->getValueType(0);
18608 if (
N->getNumOperands() == 2 &&
18612 N->getOperand(0).getOperand(1),
18613 N->getOperand(1).getOperand(0),
18614 N->getOperand(1).getOperand(1));
18617 if (
N->getNumOperands() == 2 &&
18623 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18624 S0->getOperand(1) ==
S1->getOperand(1)) {
18627 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18647 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18648 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18649 (Op.getOpcode() == ISD::BITCAST &&
18650 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18653 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18655 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18673 int NumIns =
N->getNumOperands();
18674 assert((NumIns == 2 || NumIns == 4) &&
18675 "Expected 2 or 4 inputs to an MVETrunc");
18677 if (
N->getNumOperands() == 4)
18681 for (
int I = 0;
I < NumIns;
I++) {
18683 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18703 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18706 EVT FromVT = LD->getMemoryVT();
18707 EVT ToVT =
N->getValueType(0);
18714 unsigned NumElements = 0;
18715 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18717 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18719 assert(NumElements != 0);
18725 LD->getExtensionType() != NewExtType)
18732 SDValue BasePtr = LD->getBasePtr();
18733 Align Alignment = LD->getBaseAlign();
18752 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18753 Alignment, MMOFlags, AAInfo);
18769 EVT VT =
N->getValueType(0);
18771 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18772 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18774 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18776 auto Extend = [&](
SDValue V) {
18786 SDValue Ext = Extend(
N->getOperand(0));
18794 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18799 auto CheckInregMask = [&](
int Start,
int Offset) {
18801 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18807 if (CheckInregMask(0, 0))
18809 else if (CheckInregMask(0, 1))
18810 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18811 else if (CheckInregMask(0, Mask.size()))
18813 else if (CheckInregMask(0, Mask.size() + 1))
18814 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18819 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18823 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18830 if (
N->getOperand(0)->getOpcode() == ISD::LOAD)
18841 int NumOuts =
N->getNumValues();
18842 assert((NumOuts == 2 || NumOuts == 4) &&
18843 "Expected 2 or 4 outputs to an MVEEXT");
18844 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18846 if (
N->getNumOperands() == 4)
18852 StackPtr, MPI,
Align(4));
18855 for (
int I = 0;
I < NumOuts;
I++) {
18857 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18858 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18863 VT, Chain,
Ptr, MPI, LoadVT,
Align(4));
18872 switch (
N->getOpcode()) {
18923 case ISD::FP_EXTEND:
18962 case ISD::VECREDUCE_ADD:
18989 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18996 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19007 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19015 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19017 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19025 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19027 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19035 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19046 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19054 if (
N->getOperand(1) ==
N->getOperand(2))
19055 return N->getOperand(1);
19059 switch (
N->getConstantOperandVal(1)) {
19060 case Intrinsic::arm_neon_vld1:
19061 case Intrinsic::arm_neon_vld1x2:
19062 case Intrinsic::arm_neon_vld1x3:
19063 case Intrinsic::arm_neon_vld1x4:
19064 case Intrinsic::arm_neon_vld2:
19065 case Intrinsic::arm_neon_vld3:
19066 case Intrinsic::arm_neon_vld4:
19067 case Intrinsic::arm_neon_vld2lane:
19068 case Intrinsic::arm_neon_vld3lane:
19069 case Intrinsic::arm_neon_vld4lane:
19070 case Intrinsic::arm_neon_vld2dup:
19071 case Intrinsic::arm_neon_vld3dup:
19072 case Intrinsic::arm_neon_vld4dup:
19073 case Intrinsic::arm_neon_vst1:
19074 case Intrinsic::arm_neon_vst1x2:
19075 case Intrinsic::arm_neon_vst1x3:
19076 case Intrinsic::arm_neon_vst1x4:
19077 case Intrinsic::arm_neon_vst2:
19078 case Intrinsic::arm_neon_vst3:
19079 case Intrinsic::arm_neon_vst4:
19080 case Intrinsic::arm_neon_vst2lane:
19081 case Intrinsic::arm_neon_vst3lane:
19082 case Intrinsic::arm_neon_vst4lane:
19084 case Intrinsic::arm_mve_vld2q:
19085 case Intrinsic::arm_mve_vld4q:
19086 case Intrinsic::arm_mve_vst2q:
19087 case Intrinsic::arm_mve_vst4q:
19098 return (VT == MVT::f32) && (
Opc == ISD::LOAD ||
Opc == ISD::STORE);
19104 unsigned *
Fast)
const {
19110 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19113 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19115 if (AllowsUnaligned) {
19117 *
Fast = Subtarget->hasV7Ops();
19122 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19126 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19133 if (!Subtarget->hasMVEIntegerOps())
19137 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19138 Ty == MVT::v2i1)) {
19146 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19162 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19163 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19164 Ty == MVT::v2f64) {
19175 const AttributeList &FuncAttributes)
const {
19177 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19178 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19180 if (
Op.size() >= 16 &&
19186 }
else if (
Op.size() >= 8 &&
19203 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19205 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19207 return (SrcBits == 64 && DestBits == 32);
19216 return (SrcBits == 64 && DestBits == 32);
19252 return Subtarget->hasFullFP16();
19259 if (!Subtarget->hasMVEIntegerOps())
19278 if (Ld->isExpandingLoad())
19282 if (Subtarget->hasMVEIntegerOps())
19327bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19329 if (Subtarget->useSoftFloat())
19338 return Subtarget->hasMVEFloatOps();
19356 unsigned Scale = 1;
19373 if ((V & (Scale - 1)) != 0)
19382 if (VT.
isVector() && Subtarget->hasNEON())
19385 !Subtarget->hasMVEFloatOps())
19388 bool IsNeg =
false;
19394 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19397 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19413 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19419 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19449 default:
return false;
19468 int Scale = AM.
Scale;
19473 default:
return false;
19481 Scale = Scale & ~1;
19482 return Scale == 2 || Scale == 4 || Scale == 8;
19499 if (Scale & 1)
return false;
19506 const int Scale = AM.
Scale;
19516 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19532 switch (AM.
Scale) {
19543 if (Subtarget->isThumb1Only())
19546 if (Subtarget->isThumb2())
19549 int Scale = AM.
Scale;
19551 default:
return false;
19555 if (Scale < 0) Scale = -Scale;
19563 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19576 if (Scale & 1)
return false;
19589 if (!Subtarget->isThumb())
19592 if (Subtarget->isThumb2())
19596 return Imm >= 0 && Imm <= 255;
19606 if (!Subtarget->isThumb())
19608 if (Subtarget->isThumb2())
19611 return AbsImm <= 255;
19646 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19650 int RHSC = (int)
RHS->getZExtValue();
19651 if (RHSC < 0 && RHSC > -256) {
19661 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19664 int RHSC = (int)
RHS->getZExtValue();
19665 if (RHSC < 0 && RHSC > -0x1000) {
19707 int RHSC = (int)
RHS->getZExtValue();
19708 if (RHSC < 0 && RHSC > -0x100) {
19713 }
else if (RHSC > 0 && RHSC < 0x100) {
19724 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19735 bool CanChangeType = isLE && !IsMasked;
19738 int RHSC = (int)
RHS->getZExtValue();
19740 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19741 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19746 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19757 if (VT == MVT::v4i16) {
19758 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19760 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19761 if (IsInRange(RHSC, 0x80, 1))
19763 }
else if (Alignment >= 4 &&
19764 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19765 IsInRange(RHSC, 0x80, 4))
19767 else if (Alignment >= 2 &&
19768 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19769 IsInRange(RHSC, 0x80, 2))
19771 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19784 if (Subtarget->isThumb1Only())
19790 bool isSEXTLoad =
false;
19791 bool IsMasked =
false;
19793 Ptr = LD->getBasePtr();
19794 VT = LD->getMemoryVT();
19795 Alignment = LD->getAlign();
19798 Ptr = ST->getBasePtr();
19799 VT = ST->getMemoryVT();
19800 Alignment = ST->getAlign();
19802 Ptr = LD->getBasePtr();
19803 VT = LD->getMemoryVT();
19804 Alignment = LD->getAlign();
19808 Ptr = ST->getBasePtr();
19809 VT = ST->getMemoryVT();
19810 Alignment = ST->getAlign();
19816 bool isLegal =
false;
19818 isLegal = Subtarget->hasMVEIntegerOps() &&
19820 Ptr.getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19821 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19823 if (Subtarget->isThumb2())
19848 bool isSEXTLoad =
false, isNonExt;
19849 bool IsMasked =
false;
19851 VT = LD->getMemoryVT();
19852 Ptr = LD->getBasePtr();
19853 Alignment = LD->getAlign();
19857 VT = ST->getMemoryVT();
19858 Ptr = ST->getBasePtr();
19859 Alignment = ST->getAlign();
19860 isNonExt = !ST->isTruncatingStore();
19862 VT = LD->getMemoryVT();
19863 Ptr = LD->getBasePtr();
19864 Alignment = LD->getAlign();
19869 VT = ST->getMemoryVT();
19870 Ptr = ST->getBasePtr();
19871 Alignment = ST->getAlign();
19872 isNonExt = !ST->isTruncatingStore();
19877 if (Subtarget->isThumb1Only()) {
19880 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19881 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19884 if (!RHS || RHS->getZExtValue() != 4)
19886 if (Alignment <
Align(4))
19890 Base =
Op->getOperand(0);
19896 bool isLegal =
false;
19898 isLegal = Subtarget->hasMVEIntegerOps() &&
19903 if (Subtarget->isThumb2())
19917 !Subtarget->isThumb2())
19931 const APInt &DemandedElts,
19933 unsigned Depth)
const {
19936 switch (
Op.getOpcode()) {
19943 if (
Op.getResNo() == 0) {
19969 case Intrinsic::arm_ldaex:
19970 case Intrinsic::arm_ldrex: {
19985 const APInt &Mask =
Op.getConstantOperandAPInt(2);
19986 Known.
Zero &= Mask;
19992 const SDValue &SrcSV =
Op.getOperand(0);
19998 "VGETLANE index out of bounds");
20003 EVT VT =
Op.getValueType();
20010 Known = Known.
sext(DstSz);
20012 Known = Known.
zext(DstSz);
20020 Known = KnownOp.
zext(32);
20047 unsigned Encoded =
Op.getConstantOperandVal(1);
20048 unsigned DecEltBits = 0;
20051 unsigned EltBits =
Op.getScalarValueSizeInBits();
20052 if (EltBits != DecEltBits) {
20062 APInt Imm(DecEltBits, DecodedVal);
20064 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20065 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20083 EVT VT =
Op.getValueType();
20089 assert(VT == MVT::i32 &&
"Unexpected integer type");
20096 unsigned Mask =
C->getZExtValue();
20099 unsigned ShrunkMask = Mask & Demanded;
20100 unsigned ExpandedMask = Mask | ~Demanded;
20104 if (ShrunkMask == 0)
20110 if (ExpandedMask == ~0U)
20113 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20114 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20116 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20117 if (NewMask == Mask)
20126 if (IsLegalMask(0xFF))
20127 return UseMask(0xFF);
20130 if (IsLegalMask(0xFFFF))
20131 return UseMask(0xFFFF);
20135 if (ShrunkMask < 256)
20136 return UseMask(ShrunkMask);
20140 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20141 return UseMask(ExpandedMask);
20156 unsigned Depth)
const {
20157 unsigned Opc =
Op.getOpcode();
20165 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20167 unsigned ShAmt =
Op->getConstantOperandVal(2);
20179 unsigned ModImm =
Op.getConstantOperandVal(1);
20180 unsigned EltBits = 0;
20182 if ((OriginalDemandedBits & Mask) == 0)
20188 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20203 if (!Subtarget->hasVFP2Base())
20207 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20219 unsigned S = Constraint.
size();
20221 switch (Constraint[0]) {
20233 }
else if (S == 2) {
20234 switch (Constraint[0]) {
20251 Value *CallOperandVal =
info.CallOperandVal;
20254 if (!CallOperandVal)
20258 switch (*constraint) {
20264 if (Subtarget->isThumb())
20279 if (PR == 0 || VT == MVT::Other)
20281 if (ARM::SPRRegClass.
contains(PR))
20282 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20283 if (ARM::DPRRegClass.
contains(PR))
20288using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20292 switch (Constraint.
size()) {
20295 switch (Constraint[0]) {
20297 if (Subtarget->isThumb())
20298 return RCPair(0U, &ARM::tGPRRegClass);
20299 return RCPair(0U, &ARM::GPRRegClass);
20301 if (Subtarget->isThumb())
20302 return RCPair(0U, &ARM::hGPRRegClass);
20305 if (Subtarget->isThumb1Only())
20306 return RCPair(0U, &ARM::tGPRRegClass);
20307 return RCPair(0U, &ARM::GPRRegClass);
20309 if (VT == MVT::Other)
20311 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20312 return RCPair(0U, &ARM::SPRRegClass);
20314 return RCPair(0U, &ARM::DPRRegClass);
20316 return RCPair(0U, &ARM::QPRRegClass);
20319 if (VT == MVT::Other)
20321 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20322 return RCPair(0U, &ARM::SPR_8RegClass);
20324 return RCPair(0U, &ARM::DPR_8RegClass);
20326 return RCPair(0U, &ARM::QPR_8RegClass);
20329 if (VT == MVT::Other)
20331 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20332 return RCPair(0U, &ARM::SPRRegClass);
20334 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20336 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20342 if (Constraint[0] ==
'T') {
20343 switch (Constraint[1]) {
20347 return RCPair(0U, &ARM::tGPREvenRegClass);
20349 return RCPair(0U, &ARM::tGPROddRegClass);
20358 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20359 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20363 return {0,
nullptr};
20371 std::vector<SDValue> &
Ops,
20376 if (Constraint.
size() != 1)
20379 char ConstraintLetter = Constraint[0];
20380 switch (ConstraintLetter) {
20383 case 'I':
case 'J':
case 'K':
case 'L':
20384 case 'M':
case 'N':
case 'O':
20389 int64_t CVal64 =
C->getSExtValue();
20390 int CVal = (int) CVal64;
20393 if (CVal != CVal64)
20396 switch (ConstraintLetter) {
20400 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20401 if (CVal >= 0 && CVal <= 65535)
20405 if (Subtarget->isThumb1Only()) {
20408 if (CVal >= 0 && CVal <= 255)
20410 }
else if (Subtarget->isThumb2()) {
20424 if (Subtarget->isThumb1Only()) {
20429 if (CVal >= -255 && CVal <= -1)
20435 if (CVal >= -4095 && CVal <= 4095)
20441 if (Subtarget->isThumb1Only()) {
20448 }
else if (Subtarget->isThumb2()) {
20468 if (Subtarget->isThumb1Only()) {
20471 if (CVal >= -7 && CVal < 7)
20473 }
else if (Subtarget->isThumb2()) {
20493 if (Subtarget->isThumb1Only()) {
20496 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20502 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20508 if (Subtarget->isThumb1Only()) {
20510 if (CVal >= 0 && CVal <= 31)
20516 if (Subtarget->isThumb1Only()) {
20519 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20528 if (Result.getNode()) {
20529 Ops.push_back(Result);
20539 "Unhandled Opcode in getDivRemLibcall");
20545 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20546 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20547 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20548 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20557 "Unhandled Opcode in getDivRemArgList");
20561 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20562 EVT ArgVT =
N->getOperand(i).getValueType();
20567 Args.push_back(Entry);
20575 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20576 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20577 Subtarget->isTargetWindows()) &&
20578 "Register-based DivRem lowering only");
20579 unsigned Opcode =
Op->getOpcode();
20581 "Invalid opcode for Div/Rem lowering");
20583 EVT VT =
Op->getValueType(0);
20605 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20606 : Subtarget->hasDivideInARMMode();
20607 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20608 Op->getSimpleValueType(0) == MVT::i32) {
20610 const SDValue Dividend =
Op->getOperand(0);
20611 const SDValue Divisor =
Op->getOperand(1);
20612 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20616 SDValue Values[2] = {Div, Rem};
20633 if (Subtarget->isTargetWindows())
20636 TargetLowering::CallLoweringInfo CLI(DAG);
20641 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20642 return CallInfo.first;
20648 EVT VT =
N->getValueType(0);
20654 Result[0], Result[1]);
20658 std::vector<Type*> RetTyParams;
20659 Type *RetTyElement;
20669 RetTyParams.push_back(RetTyElement);
20670 RetTyParams.push_back(RetTyElement);
20683 if (Subtarget->isTargetWindows())
20691 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20694 SDNode *ResNode = CallResult.first.getNode();
20701 assert(Subtarget->isTargetWindows() &&
"unsupported target platform");
20709 "no-stack-arg-probe")) {
20713 Chain =
SP.getValue(1);
20730 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20741 bool IsStrict =
Op->isStrictFPOpcode();
20742 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20743 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20745 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20746 "Unexpected type for custom-lowering FP_EXTEND");
20748 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20749 "With both FP DP and 16, any FP conversion is legal!");
20751 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20752 "With FP16, 16 to 32 conversion is legal!");
20755 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20760 Loc,
Op.getValueType(), SrcVal);
20775 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20776 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20777 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20778 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20782 {DstVT, MVT::Other}, {Chain, SrcVal});
20785 SrcVal = DAG.
getNode(ISD::FP_EXTEND, Loc, DstVT, SrcVal);
20789 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20790 "Unexpected type for custom-lowering FP_EXTEND");
20791 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20796 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20800 bool IsStrict =
Op->isStrictFPOpcode();
20802 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20804 EVT DstVT =
Op.getValueType();
20805 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20808 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20809 "Unexpected type for custom-lowering FP_ROUND");
20811 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20812 "With both FP DP and 16, any FP conversion is legal!");
20817 if (SrcSz == 32 && Subtarget->hasFP16())
20822 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20823 "Unexpected type for custom-lowering FP_ROUND");
20827 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20839 if (v == 0xffffffff)
20851 bool ForCodeSize)
const {
20852 if (!Subtarget->hasVFP3Base())
20854 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20856 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20859 if (VT == MVT::f32)
20861 if (VT == MVT::f64 && Subtarget->hasFP64())
20874 case Intrinsic::arm_neon_vld1:
20875 case Intrinsic::arm_neon_vld2:
20876 case Intrinsic::arm_neon_vld3:
20877 case Intrinsic::arm_neon_vld4:
20878 case Intrinsic::arm_neon_vld2lane:
20879 case Intrinsic::arm_neon_vld3lane:
20880 case Intrinsic::arm_neon_vld4lane:
20881 case Intrinsic::arm_neon_vld2dup:
20882 case Intrinsic::arm_neon_vld3dup:
20883 case Intrinsic::arm_neon_vld4dup: {
20886 auto &
DL =
I.getDataLayout();
20887 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20889 Info.ptrVal =
I.getArgOperand(0);
20891 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20897 case Intrinsic::arm_neon_vld1x2:
20898 case Intrinsic::arm_neon_vld1x3:
20899 case Intrinsic::arm_neon_vld1x4: {
20902 auto &
DL =
I.getDataLayout();
20903 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20905 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20907 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20912 case Intrinsic::arm_neon_vst1:
20913 case Intrinsic::arm_neon_vst2:
20914 case Intrinsic::arm_neon_vst3:
20915 case Intrinsic::arm_neon_vst4:
20916 case Intrinsic::arm_neon_vst2lane:
20917 case Intrinsic::arm_neon_vst3lane:
20918 case Intrinsic::arm_neon_vst4lane: {
20921 auto &
DL =
I.getDataLayout();
20922 unsigned NumElts = 0;
20923 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20924 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20927 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20930 Info.ptrVal =
I.getArgOperand(0);
20932 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20938 case Intrinsic::arm_neon_vst1x2:
20939 case Intrinsic::arm_neon_vst1x3:
20940 case Intrinsic::arm_neon_vst1x4: {
20943 auto &
DL =
I.getDataLayout();
20944 unsigned NumElts = 0;
20945 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20946 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20949 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20952 Info.ptrVal =
I.getArgOperand(0);
20954 Info.align =
I.getParamAlign(0).valueOrOne();
20959 case Intrinsic::arm_mve_vld2q:
20960 case Intrinsic::arm_mve_vld4q: {
20964 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
20966 Info.ptrVal =
I.getArgOperand(0);
20973 case Intrinsic::arm_mve_vst2q:
20974 case Intrinsic::arm_mve_vst4q: {
20977 Type *VecTy =
I.getArgOperand(1)->getType();
20978 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
20980 Info.ptrVal =
I.getArgOperand(0);
20987 case Intrinsic::arm_mve_vldr_gather_base:
20988 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
20990 Info.ptrVal =
nullptr;
20992 Info.align =
Align(1);
20996 case Intrinsic::arm_mve_vldr_gather_base_wb:
20997 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
20999 Info.ptrVal =
nullptr;
21000 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21001 Info.align =
Align(1);
21005 case Intrinsic::arm_mve_vldr_gather_offset:
21006 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21008 Info.ptrVal =
nullptr;
21013 Info.align =
Align(1);
21017 case Intrinsic::arm_mve_vstr_scatter_base:
21018 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21020 Info.ptrVal =
nullptr;
21021 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21022 Info.align =
Align(1);
21026 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21027 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21029 Info.ptrVal =
nullptr;
21030 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21031 Info.align =
Align(1);
21035 case Intrinsic::arm_mve_vstr_scatter_offset:
21036 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21038 Info.ptrVal =
nullptr;
21043 Info.align =
Align(1);
21047 case Intrinsic::arm_ldaex:
21048 case Intrinsic::arm_ldrex: {
21049 auto &
DL =
I.getDataLayout();
21050 Type *ValTy =
I.getParamElementType(0);
21053 Info.ptrVal =
I.getArgOperand(0);
21055 Info.align =
DL.getABITypeAlign(ValTy);
21059 case Intrinsic::arm_stlex:
21060 case Intrinsic::arm_strex: {
21061 auto &
DL =
I.getDataLayout();
21062 Type *ValTy =
I.getParamElementType(1);
21065 Info.ptrVal =
I.getArgOperand(1);
21067 Info.align =
DL.getABITypeAlign(ValTy);
21071 case Intrinsic::arm_stlexd:
21072 case Intrinsic::arm_strexd:
21074 Info.memVT = MVT::i64;
21075 Info.ptrVal =
I.getArgOperand(2);
21077 Info.align =
Align(8);
21081 case Intrinsic::arm_ldaexd:
21082 case Intrinsic::arm_ldrexd:
21084 Info.memVT = MVT::i64;
21085 Info.ptrVal =
I.getArgOperand(0);
21087 Info.align =
Align(8);
21102 assert(Ty->isIntegerTy());
21104 unsigned Bits = Ty->getPrimitiveSizeInBits();
21105 if (Bits == 0 || Bits > 32)
21111 unsigned Index)
const {
21121 if (!Subtarget->hasDataBarrier()) {
21125 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21126 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21127 Builder.getInt32(0), Builder.getInt32(7),
21128 Builder.getInt32(10), Builder.getInt32(5)};
21129 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
21139 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
21160 if (Subtarget->preferISHSTBarriers())
21193 bool has64BitAtomicStore;
21194 if (Subtarget->isMClass())
21195 has64BitAtomicStore =
false;
21196 else if (Subtarget->isThumb())
21197 has64BitAtomicStore = Subtarget->hasV7Ops();
21199 has64BitAtomicStore = Subtarget->hasV6Ops();
21201 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21215 bool has64BitAtomicLoad;
21216 if (Subtarget->isMClass())
21217 has64BitAtomicLoad =
false;
21218 else if (Subtarget->isThumb())
21219 has64BitAtomicLoad = Subtarget->hasV7Ops();
21221 has64BitAtomicLoad = Subtarget->hasV6Ops();
21237 if (Subtarget->isMClass())
21238 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21239 else if (Subtarget->isThumb())
21240 hasAtomicRMW = Subtarget->hasV7Ops();
21242 hasAtomicRMW = Subtarget->hasV6Ops();
21243 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21266 bool HasAtomicCmpXchg;
21267 if (Subtarget->isMClass())
21268 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21269 else if (Subtarget->isThumb())
21270 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21272 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21274 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21281 return InsertFencesForAtomic;
21286 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21290 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21292 if (SecurityCheckCookieLibcall == RTLIB::Unsupported)
21296 M.getOrInsertGlobal(
"__security_cookie",
21304 F->addParamAttr(0, Attribute::AttrKind::InReg);
21309 RTLIB::LibcallImpl SecurityCheckCookie =
21311 if (SecurityCheckCookie != RTLIB::Unsupported)
21317 unsigned &
Cost)
const {
21319 if (!Subtarget->hasNEON())
21348 unsigned Opcode =
Op.getOpcode();
21359 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21363 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21368 if (!Subtarget->hasV7Ops())
21374 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21376 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21384 if (Subtarget->hasMinSize() && !Subtarget->isTargetWindows())
21393 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21399 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21401 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21404 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21406 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21407 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21408 if (!Subtarget->isLittle())
21410 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21411 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21412 return Builder.CreateOr(
21413 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21417 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21418 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21421 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21422 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21427 if (!Subtarget->hasV7Ops())
21429 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21435 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21443 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21447 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21448 if (!Subtarget->isLittle())
21450 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21453 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21457 CallInst *CI = Builder.CreateCall(
21458 Strex, {Builder.CreateZExtOrBitCast(
21468 return Subtarget->isMClass();
21476 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21483 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21486 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21494 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21502 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21505 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21510 if (Subtarget->hasNEON() && VecSize == 64)
21512 return VecSize % 128 == 0;
21516 if (Subtarget->hasNEON())
21518 if (Subtarget->hasMVEIntegerOps())
21538 "Invalid interleave factor");
21539 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21541 "Unmatched number of shufflevectors and indices");
21546 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21549 Type *EltTy = VecTy->getElementType();
21552 Align Alignment = LI->getAlign();
21570 Value *BaseAddr = LI->getPointerOperand();
21572 if (NumLoads > 1) {
21576 VecTy->getNumElements() / NumLoads);
21582 if (Subtarget->hasNEON()) {
21583 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21584 Type *Tys[] = {VecTy, PtrTy};
21585 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21586 Intrinsic::arm_neon_vld3,
21587 Intrinsic::arm_neon_vld4};
21590 Ops.push_back(BaseAddr);
21591 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21593 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21596 assert((Factor == 2 || Factor == 4) &&
21597 "expected interleave factor of 2 or 4 for MVE");
21599 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21600 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21601 Type *Tys[] = {VecTy, PtrTy};
21604 Ops.push_back(BaseAddr);
21605 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21615 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21619 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21620 VecTy->getNumElements() * Factor);
21626 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21628 unsigned Index = Indices[i];
21630 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21634 SubVec = Builder.CreateIntToPtr(
21638 SubVecs[SV].push_back(SubVec);
21647 auto &SubVec = SubVecs[SVI];
21650 SVI->replaceAllUsesWith(WideVec);
21686 const APInt &GapMask)
const {
21688 "Invalid interleave factor");
21693 "Unexpected mask on store");
21696 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21698 unsigned LaneLen = VecTy->getNumElements() / Factor;
21699 Type *EltTy = VecTy->getElementType();
21703 Align Alignment =
SI->getAlign();
21720 Type *IntTy =
DL.getIntPtrType(EltTy);
21725 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21726 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21732 Value *BaseAddr =
SI->getPointerOperand();
21734 if (NumStores > 1) {
21737 LaneLen /= NumStores;
21747 if (Subtarget->hasNEON()) {
21748 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21749 Intrinsic::arm_neon_vst3,
21750 Intrinsic::arm_neon_vst4};
21751 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21752 Type *Tys[] = {PtrTy, SubVecTy};
21755 Ops.push_back(BaseAddr);
21757 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21758 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21760 assert((Factor == 2 || Factor == 4) &&
21761 "expected interleave factor of 2 or 4 for MVE");
21763 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21764 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21765 Type *Tys[] = {PtrTy, SubVecTy};
21768 Ops.push_back(BaseAddr);
21770 for (
unsigned F = 0;
F < Factor;
F++) {
21771 Ops.push_back(Builder.getInt32(
F));
21772 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21778 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21781 if (StoreCount > 0)
21782 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21783 BaseAddr, LaneLen * Factor);
21788 for (
unsigned i = 0; i < Factor; i++) {
21789 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21790 if (Mask[IdxI] >= 0) {
21791 Shuffles.
push_back(Builder.CreateShuffleVector(
21794 unsigned StartMask = 0;
21795 for (
unsigned j = 1; j < LaneLen; j++) {
21796 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21797 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21798 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21808 Shuffles.
push_back(Builder.CreateShuffleVector(
21829 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21833 Members += SubMembers;
21839 Members += SubMembers * AT->getNumElements();
21840 }
else if (Ty->isFloatTy()) {
21845 }
else if (Ty->isDoubleTy()) {
21857 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21859 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21861 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21874 return (Members > 0 && Members <= 4);
21880 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21882 return ABITypeAlign;
21887 assert(StackAlign &&
"data layout string is missing stack alignment");
21888 return std::min(ABITypeAlign, *StackAlign);
21897 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21906 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
21907 return IsHA || IsIntArray;
21911 const Constant *PersonalityFn)
const {
21919 const Constant *PersonalityFn)
const {
21932void ARMTargetLowering::insertCopiesSplitCSR(
21936 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21946 RC = &ARM::GPRRegClass;
21947 else if (ARM::DPRRegClass.
contains(*
I))
21948 RC = &ARM::DPRRegClass;
21958 assert(Entry->getParent()->getFunction().hasFnAttribute(
21959 Attribute::NoUnwind) &&
21960 "Function should be nounwind in insertCopiesSplitCSR!");
21961 Entry->addLiveIn(*
I);
21966 for (
auto *Exit : Exits)
21968 TII->get(TargetOpcode::COPY), *
I)
21979 return Subtarget->hasMVEIntegerOps();
21989 unsigned NumElements = VTy->getNumElements();
21996 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
21997 return Subtarget->hasMVEFloatOps();
22002 return Subtarget->hasMVEIntegerOps() &&
22003 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22004 ScalarTy->isIntegerTy(32));
22014 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22016 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22018 if (TyWidth > 128) {
22019 int Stride = Ty->getNumElements() / 2;
22023 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22025 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22026 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22027 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22028 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22029 Value *LowerSplitAcc =
nullptr;
22030 Value *UpperSplitAcc =
nullptr;
22033 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22034 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22038 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22040 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22042 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22043 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22050 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22053 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22055 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22056 {ConstRotation, InputB, InputA});
22061 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22064 ConstRotation = ConstantInt::get(IntTy, 0);
22066 ConstRotation = ConstantInt::get(IntTy, 1);
22068 if (!ConstRotation)
22071 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22072 {ConstHalving, ConstRotation, InputA, InputB});
unsigned const MachineRegisterInfo * MRI
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool isNegatedInteger(SDValue Op)
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue LowerUADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue ConvertBooleanCarryToCarryFlag(SDValue BoolCarry, SelectionDAG &DAG)
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue ConvertCarryFlagToBooleanCarry(SDValue Flags, EVT VT, SelectionDAG &DAG)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static unsigned SelectPairHalf(unsigned Elements, ArrayRef< int > Mask, unsigned Index)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerTruncate(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformHWLoopCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, Value *Offset, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, Value *Offset, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned int Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first found DebugLoc that has a DILocation, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
unsigned logBase2() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
virtual const ARMBaseRegisterInfo & getRegisterInfo() const =0
const uint32_t * getSjLjDispatchPreservedMask(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const uint32_t * getTLSCallPreservedMask(const MachineFunction &MF) const
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
int getVarArgsFrameIndex() const
int getPromotedConstpoolIncrease() const
SmallPtrSet< const GlobalVariable *, 2 > & getGlobalsPromotedToConstantPool()
void setArgumentStackToRestore(unsigned v)
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
void setPromotedConstpoolIncrease(int Sz)
bool isThumb1OnlyFunction() const
void setArgRegsSaveSize(unsigned s)
bool isCmseNSEntryFunction() const
void setReturnRegsCount(unsigned s)
void setVarArgsFrameIndex(int Index)
unsigned getArgRegsSaveSize() const
void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV)
Indicate to the backend that GV has had its storage changed to inside a constant pool.
void setIsSplitCSR(bool s)
void setArgumentStackSize(unsigned size)
unsigned getArgumentStackSize() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
bool isTargetWindows() const
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
Align getDualLoadStoreAlignment() const
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool isReadOnly(const GlobalValue *GV) const
unsigned getMaxSupportedInterleaveFactor() const override
Get the maximum supported factor for interleaved memory accesses.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
unsigned getNumInterleavedAccesses(VectorType *VecTy, const DataLayout &DL) const
Returns the number of interleaved accesses that will be generated when lowering accesses of the given...
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Align getABIAlignmentForCallingConv(Type *ArgTy, const DataLayout &DL) const override
Return the correct alignment for the current calling convention.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
Function * getSSPStackGuardCheck(const Module &M) const override
If the target has a standard stack protection check function that performs validation and error handl...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void insertSSPDeclarations(Module &M) const override
Inserts necessary declarations for SSP (stack protection) purpose.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override
Return true if it is profitable to combine an XOR of a logical shift to create a logical shift of NOT...
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const
PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
Value * createComplexDeinterleavingIR(IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, Value *Accumulator=nullptr) const override
Create the IR node for the given complex deinterleaving operation.
bool isComplexDeinterleavingSupported() const override
Does this target support complex deinterleaving.
SDValue PerformMVEExtCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool shouldFoldConstantShiftPairToMask(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to fold a pair of shifts into a mask.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &OriginalDemandedBits, const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the value type to use for ISD::SETCC.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const override
Perform a store-conditional operation to Addr.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool isVarArg) const
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for this result type with this index.
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
isShuffleMaskLegal - Targets can use this to indicate that they only support some VECTOR_SHUFFLE oper...
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
bool lowerInterleavedStore(Instruction *Store, Value *Mask, ShuffleVectorInst *SVI, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved store into a vstN intrinsic.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
bool useLoadStackGuardNode(const Module &M) const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vldN intrinsic.
std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override
Return the largest legal super-reg register class of the register class for the specified type and it...
bool 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.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
const char * getTargetNodeName(unsigned Opcode) const override
This method returns the name of a target specific DAG node.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool isVarArg) const
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
allowsMisalignedMemoryAccesses - Returns true if the target allows unaligned memory accesses of the s...
bool isLegalInterleavedAccessType(unsigned Factor, FixedVectorType *VecTy, Align Alignment, const DataLayout &DL) const
Returns true if VecTy is a legal interleaved access type.
bool isVectorLoadExtDesirable(SDValue ExtVal) const override
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, unsigned &Cost) const override
Return true if the target can combine store(extractelement VectorTy,Idx).
bool useSoftFloat() const override
bool alignLoopsWithOptSize() const override
Should loops be aligned even when the function is marked OptSize (but not MinSize).
SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const
bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override
Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail ...
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
bool isFloatingPointOperation() const
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
The address of a basic block.
static BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
LLVM_ABI int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, uint32_t BitWidth) const
If this is a constant FP splat and the splatted constant FP is an exact power or 2,...
CCState - This class holds information needed while lowering arguments and return values.
void getInRegsParamInfo(unsigned InRegsParamRecordIndex, unsigned &BeginReg, unsigned &EndReg) const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
void rewindByValRegsInfo()
unsigned getInRegsParamsProcessed() const
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd)
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
unsigned getInRegsParamsCount() const
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
const APFloat & getValueAPF() const
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
MaybeAlign getStackAlignment() const
Returns the natural stack alignment, or MaybeAlign() if one wasn't specified.
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
StringRef getPrivateGlobalPrefix() const
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Describe properties that are true of each instruction in the target description file.
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
bool is64BitVector() const
Return true if this is a 64-bit vector type.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI unsigned createJumpTableIndex(const std::vector< MachineBasicBlock * > &DestBBs)
createJumpTableIndex - Create a new jump table.
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
This class is used to represent an MLOAD node.
This class is used to represent an MSTORE node.
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags)
Get the specified node if it's already available, or else return NULL.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
This instruction constructs a fixed permutation of two input vectors.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
StringRef - Represent a constant reference to a string, i.e.
const unsigned char * bytes_end() const
constexpr size_t size() const
size - Get the string size.
const unsigned char * bytes_begin() const
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
Provides information about what library functions are available for the current target.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const
Get the CallingConv that should be used for the specified libcall.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
ShiftLegalizationStrategy
Return the preferred strategy to legalize tihs SHIFT instruction, with ExpansionFactor being the recu...
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
const TargetMachine & getTargetMachine() const
void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked load does or does not work with the specified type and ind...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual Function * getSSPStackGuardCheck(const Module &M) const
If the target has a standard stack protection check function that performs validation and error handl...
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked store does or does not work with the specified type and in...
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
static StringRef getLibcallImplName(RTLIB::LibcallImpl Call)
Get the libcall routine name for the specified libcall implementation.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl)
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
virtual void insertSSPDeclarations(Module &M) const
Inserts necessary declarations for SSP (stack protection) purpose.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool expandDIVREMByConstant(SDNode *N, SmallVectorImpl< SDValue > &Result, EVT HiLoVT, SelectionDAG &DAG, SDValue LL=SDValue(), SDValue LH=SDValue()) const
Attempt to expand an n-bit div/rem/divrem by constant using a n/2-bit urem by constant and other arit...
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
ExceptionHandling getExceptionModel() const
Return the ExceptionHandling to use, considering TargetOptions and the Triple's default.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
unsigned EmitCallGraphSection
Emit section containing call graph metadata.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
Base class of all SIMD vector types.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static CondCodes getOppositeCondition(CondCodes CC)
@ SECREL
Thread Pointer Offset.
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
TOF
Target Operand Flag enum.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2Offset(unsigned AM2Opc)
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
AddrOpc getAM2Op(unsigned AM2Opc)
bool isBitFieldInvertedMask(unsigned v)
const unsigned FPStatusBits
const unsigned FPReservedBits
const unsigned RoundingBitsPos
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Swift
Calling convention for Swift.
@ ARM_APCS
ARM Procedure Calling Standard (obsolete, but still used on some targets).
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ ARM_AAPCS
ARM Architecture Procedure Calling Standard calling convention (aka EABI).
@ CXX_FAST_TLS
Used for access functions.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ ARM_AAPCS_VFP
Same as ARM_AAPCS, but uses hard floating point ABI.
@ C
The default llvm calling convention, compatible with C.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
@ FGETSIGN
INT = FGETSIGN(FP) - Return the sign bit of the specified floating point value as an integer 0/1 valu...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ EH_SJLJ_SETUP_DISPATCH
OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) The target initializes the dispatch table here.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ SSUBO
Same for subtraction.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ SMULO
Same for multiplication.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ SjLj
setjmp/longjmp based exceptions
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
FunctionAddr VTableAddr uintptr_t uintptr_t Data
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
static constexpr roundingMode rmTowardZero
This struct is a compact representation of a valid (non-zero power of two) alignment.
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 ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
bool isUnknown() const
Returns true if we don't know any bits.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
CallLoweringInfo & setDiscardResult(bool Value=true)
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)