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,
257 LegalizeAction Action) {
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)
595 if (!Subtarget->useSoftFloat() && !Subtarget->
isThumb1Only() &&
596 Subtarget->hasFPRegs()) {
606 setAllExpand(MVT::f32);
607 if (!Subtarget->hasFP64())
608 setAllExpand(MVT::f64);
611 if (Subtarget->hasFullFP16()) {
620 if (Subtarget->hasBF16()) {
622 setAllExpand(MVT::bf16);
623 if (!Subtarget->hasFullFP16())
635 addAllExtLoads(VT, InnerVT,
Expand);
644 if (!Subtarget->
isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
647 if (!Subtarget->hasV8_1MMainlineOps())
656 if (Subtarget->hasMVEIntegerOps())
657 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
660 if (Subtarget->hasLOB()) {
664 if (Subtarget->hasNEON()) {
665 addDRTypeForNEON(MVT::v2f32);
666 addDRTypeForNEON(MVT::v8i8);
667 addDRTypeForNEON(MVT::v4i16);
668 addDRTypeForNEON(MVT::v2i32);
669 addDRTypeForNEON(MVT::v1i64);
671 addQRTypeForNEON(MVT::v4f32);
672 addQRTypeForNEON(MVT::v2f64);
673 addQRTypeForNEON(MVT::v16i8);
674 addQRTypeForNEON(MVT::v8i16);
675 addQRTypeForNEON(MVT::v4i32);
676 addQRTypeForNEON(MVT::v2i64);
678 if (Subtarget->hasFullFP16()) {
679 addQRTypeForNEON(MVT::v8f16);
680 addDRTypeForNEON(MVT::v4f16);
683 if (Subtarget->hasBF16()) {
684 addQRTypeForNEON(MVT::v8bf16);
685 addDRTypeForNEON(MVT::v4bf16);
689 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
729 if (Subtarget->hasNEON()) {
851 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
860 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
869 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
877 if (Subtarget->hasMVEIntegerOps()) {
882 if (Subtarget->hasMVEFloatOps()) {
886 if (!Subtarget->hasFP64()) {
934 if (Subtarget->hasFullFP16()) {
940 if (!Subtarget->hasFP16()) {
991 if (Subtarget->hasDSP()) {
1013 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6Ops()
1014 || (Subtarget->
isThumb2() && !Subtarget->hasDSP()))
1029 if (Subtarget->hasMVEIntegerOps())
1039 if (!Subtarget->
isThumb1Only() && Subtarget->hasV6T2Ops())
1053 if (!Subtarget->hasV5TOps() || Subtarget->
isThumb1Only()) {
1062 if (Subtarget->hasPerfMon())
1066 if (!Subtarget->hasV6Ops())
1069 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1070 : Subtarget->hasDivideInARMMode();
1077 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1089 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1090 TT.isTargetMuslAEABI() || TT.isOSWindows()) {
1093 HasStandaloneRem =
false;
1120 if (TT.isOSWindows())
1127 InsertFencesForAtomic =
false;
1129 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1133 if (!Subtarget->isThumb() || !Subtarget->
isMClass())
1138 if (!Subtarget->hasAcquireRelease() ||
1141 InsertFencesForAtomic =
true;
1147 if (Subtarget->hasDataBarrier())
1148 InsertFencesForAtomic =
true;
1168 if (!InsertFencesForAtomic) {
1175 if (TT.isOSLinux() || (!Subtarget->
isMClass() && Subtarget->hasV6Ops())) {
1187 }
else if ((Subtarget->
isMClass() && Subtarget->hasV8MBaselineOps()) ||
1188 Subtarget->hasForced32BitAtomics()) {
1202 if (!Subtarget->hasV6Ops()) {
1208 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1238 if (Subtarget->hasFullFP16()) {
1248 if (Subtarget->hasFullFP16())
1263 if (!Subtarget->useSoftFloat() && Subtarget->
hasVFP2Base() &&
1277 if (!Subtarget->useSoftFloat() && !Subtarget->
isThumb1Only()) {
1285 if (!Subtarget->hasFP16()) {
1317 if (Subtarget->hasNEON()) {
1324 if (Subtarget->hasFP64()) {
1338 if (Subtarget->hasFullFP16()) {
1363 if (Subtarget->hasNEON()) {
1375 if (Subtarget->hasV8Ops()) {
1390 if (Subtarget->hasFullFP16()) {
1418 if (TT.isOSWindows()) {
1435 if (Subtarget->hasMVEIntegerOps())
1438 if (Subtarget->hasV6Ops())
1443 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1450 if (Subtarget->useSoftFloat() || Subtarget->
isThumb1Only() ||
1479 return Subtarget->useSoftFloat();
1496std::pair<const TargetRegisterClass *, uint8_t>
1507 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1508 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1509 RRC = &ARM::DPRRegClass;
1517 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1518 case MVT::v4f32:
case MVT::v2f64:
1519 RRC = &ARM::DPRRegClass;
1523 RRC = &ARM::DPRRegClass;
1527 RRC = &ARM::DPRRegClass;
1531 return std::make_pair(RRC,
Cost);
1535#define MAKE_CASE(V) \
1754 if ((Subtarget->hasMVEIntegerOps() &&
1755 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1756 VT == MVT::v16i8)) ||
1757 (Subtarget->hasMVEFloatOps() &&
1758 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1772 if (Subtarget->hasNEON()) {
1773 if (VT == MVT::v4i64)
1774 return &ARM::QQPRRegClass;
1775 if (VT == MVT::v8i64)
1776 return &ARM::QQQQPRRegClass;
1778 if (Subtarget->hasMVEIntegerOps()) {
1779 if (VT == MVT::v4i64)
1780 return &ARM::MQQPRRegClass;
1781 if (VT == MVT::v8i64)
1782 return &ARM::MQQQQPRRegClass;
1791 Align &PrefAlign)
const {
1792 if (!isa<MemIntrinsic>(CI))
1810 unsigned NumVals =
N->getNumValues();
1814 for (
unsigned i = 0; i != NumVals; ++i) {
1815 EVT VT =
N->getValueType(i);
1816 if (VT == MVT::Glue || VT == MVT::Other)
1822 if (!
N->isMachineOpcode())
1846 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
1847 return Const->getZExtValue() == 16;
1854 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
1855 return Const->getZExtValue() == 16;
1862 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
1863 return Const->getZExtValue() == 16;
1932 bool isVarArg)
const {
1951 if (!
getTM().isAAPCS_ABI())
1953 else if (Subtarget->hasFPRegs() && !Subtarget->
isThumb1Only() &&
1961 if (!
getTM().isAAPCS_ABI()) {
1974 bool isVarArg)
const {
1975 return CCAssignFnForNode(CC,
false, isVarArg);
1979 bool isVarArg)
const {
1980 return CCAssignFnForNode(CC,
true, isVarArg);
1987 bool isVarArg)
const {
1988 switch (getEffectiveCallingConv(CC, isVarArg)) {
2014 if (Subtarget->hasFullFP16()) {
2027 if (Subtarget->hasFullFP16()) {
2041SDValue ARMTargetLowering::LowerCallResult(
2045 SDValue ThisVal,
bool isCmseNSCall)
const {
2053 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
2058 if (i == 0 && isThisReturn) {
2060 "unexpected return calling convention register assignment");
2071 Chain =
Lo.getValue(1);
2072 InGlue =
Lo.getValue(2);
2076 Chain =
Hi.getValue(1);
2077 InGlue =
Hi.getValue(2);
2089 Chain =
Lo.getValue(1);
2090 InGlue =
Lo.getValue(2);
2093 Chain =
Hi.getValue(1);
2094 InGlue =
Hi.getValue(2);
2138std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
2140 bool IsTailCall,
int SPDiff)
const {
2162 return std::make_pair(DstAddr, DstInfo);
2171ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
2177 if (isa<GlobalAddressSDNode>(Src) || isa<ExternalSymbolSDNode>(Src))
2182 auto *SrcFrameIdxNode = dyn_cast<FrameIndexSDNode>(Src);
2183 auto *DstFrameIdxNode = dyn_cast<FrameIndexSDNode>(Dst);
2184 if (!SrcFrameIdxNode || !DstFrameIdxNode)
2187 int SrcFI = SrcFrameIdxNode->getIndex();
2188 int DstFI = DstFrameIdxNode->getIndex();
2190 "byval passed in non-fixed stack slot");
2212 if (SrcOffset == DstOffset)
2220 RegsToPassVector &RegsToPass,
2227 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
2228 unsigned id = Subtarget->
isLittle() ? 0 : 1;
2241 std::tie(DstAddr, DstInfo) =
2242 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2276 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].
Flags.isSRet();
2277 bool isThisReturn =
false;
2278 bool isCmseNSCall =
false;
2279 bool isSibCall =
false;
2280 bool PreferIndirect =
false;
2281 bool GuardWithBTI =
false;
2291 !Subtarget->noBTIAtReturnTwice())
2300 isCmseNSCall =
true;
2312 if (isa<GlobalAddressSDNode>(Callee)) {
2316 auto *GV = cast<GlobalAddressSDNode>(Callee)->getGlobal();
2319 PreferIndirect = Subtarget->isThumb() && Subtarget->
hasMinSize() &&
2321 return isa<Instruction>(U) &&
2322 cast<Instruction>(U)->getParent() == BB;
2329 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2343 "site marked musttail");
2346 unsigned NumBytes = CCInfo.getStackSize();
2355 if (isTailCall && !isSibCall) {
2362 assert(StackAlign &&
"data layout string is missing stack alignment");
2363 NumBytes =
alignTo(NumBytes, *StackAlign);
2368 SPDiff = NumReusableBytes - NumBytes;
2372 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2388 RegsToPassVector RegsToPass;
2403 SDValue Src = OutVals[ArgIdx];
2406 if (!
Flags.isByVal())
2411 std::tie(Dst, DstInfo) =
2412 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2413 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2415 if (Copy == NoCopy) {
2420 }
else if (Copy == CopyOnce) {
2424 ByValTemporaries[ArgIdx] = Src;
2426 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2430 int TempFrameIdx = MFI.CreateStackObject(
2431 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2440 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2443 ByValTemporaries[ArgIdx] = Temp;
2446 if (!ByValCopyChains.
empty())
2456 bool AfterFormalArgLoads =
false;
2460 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2462 ++i, ++realArgIdx) {
2464 SDValue Arg = OutVals[realArgIdx];
2466 bool isByVal =
Flags.isByVal();
2486 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2491 AfterFormalArgLoads =
true;
2503 auto ArgVT = Outs[realArgIdx].ArgVT;
2504 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2522 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2523 StackPtr, MemOpChains, isTailCall, SPDiff);
2527 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2528 StackPtr, MemOpChains, isTailCall, SPDiff);
2533 std::tie(DstAddr, DstInfo) =
2534 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2538 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2539 StackPtr, MemOpChains, isTailCall, SPDiff);
2541 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2542 Outs[0].VT == MVT::i32) {
2544 "unexpected calling convention register assignment");
2545 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2546 "unexpected use of 'returned'");
2547 isThisReturn =
true;
2552 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2553 }
else if (isByVal) {
2555 unsigned offset = 0;
2559 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2560 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2563 bool NeedsStackCopy;
2564 if (
auto It = ByValTemporaries.
find(realArgIdx);
2565 It != ByValTemporaries.
end()) {
2566 ByValSrc = It->second;
2567 NeedsStackCopy =
true;
2570 NeedsStackCopy = !isTailCall;
2574 if (CurByValIdx < ByValArgsCount) {
2575 unsigned RegBegin, RegEnd;
2576 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2580 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2587 RegsToPass.push_back(std::make_pair(j, Load));
2592 offset = RegEnd - RegBegin;
2594 CCInfo.nextInRegsParam();
2599 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2603 std::tie(Dst, DstInfo) =
2604 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2613 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2621 std::tie(DstAddr, DstInfo) =
2622 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2629 if (!MemOpChains.
empty())
2635 for (
const auto &[Reg,
N] : RegsToPass) {
2643 bool isDirect =
false;
2648 GVal =
G->getGlobal();
2649 bool isStub = !
TM.shouldAssumeDSOLocal(GVal) && Subtarget->
isTargetMachO();
2651 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->
isMClass());
2652 bool isLocalARMFunc =
false;
2655 if (Subtarget->genLongCalls()) {
2657 "long-calls codegen is not position independent!");
2661 if (isa<GlobalAddressSDNode>(Callee)) {
2662 if (Subtarget->genExecuteOnly()) {
2681 const char *
Sym = S->getSymbol();
2683 if (Subtarget->genExecuteOnly()) {
2702 }
else if (isa<GlobalAddressSDNode>(Callee)) {
2703 if (!PreferIndirect) {
2708 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2710 if (isStub && Subtarget->
isThumb1Only() && !Subtarget->hasV5TOps()) {
2722 "Windows is the only supported COFF target");
2726 else if (!
TM.shouldAssumeDSOLocal(GVal))
2742 const char *
Sym = S->getSymbol();
2743 if (isARMFunc && Subtarget->
isThumb1Only() && !Subtarget->hasV5TOps()) {
2747 ARMPCLabelIndex, 4);
2761 assert(!isARMFunc && !isDirect &&
2762 "Cannot handle call to ARM function or direct call");
2766 "call to non-secure function would require "
2767 "passing arguments on stack",
2773 "call to non-secure function would return value through pointer",
2780 if (Subtarget->isThumb()) {
2783 else if (isCmseNSCall)
2785 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2790 if (!isDirect && !Subtarget->hasV5TOps())
2792 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2805 if (isTailCall && !isSibCall) {
2810 std::vector<SDValue> Ops;
2811 Ops.push_back(Chain);
2812 Ops.push_back(Callee);
2820 for (
const auto &[Reg,
N] : RegsToPass)
2833 isThisReturn =
false;
2839 assert(Mask &&
"Missing call preserved mask for calling convention");
2843 Ops.push_back(InGlue);
2854 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue}, Ops);
2866 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2872 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2873 InVals, isThisReturn,
2874 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2881void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2882 Align Alignment)
const {
2884 Alignment = std::max(Alignment,
Align(4));
2890 unsigned AlignInRegs = Alignment.
value() / 4;
2891 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2892 for (
unsigned i = 0; i < Waste; ++i)
2898 unsigned Excess = 4 * (ARM::R4 -
Reg);
2905 if (NSAAOffset != 0 &&
Size > Excess) {
2917 unsigned ByValRegBegin =
Reg;
2918 unsigned ByValRegEnd = std::min<unsigned>(Reg +
Size / 4, ARM::R4);
2922 for (
unsigned i = Reg + 1; i != ByValRegEnd; ++i)
2928 Size = std::max<int>(
Size - Excess, 0);
2936bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2962 if (!isa<GlobalAddressSDNode>(
Callee.getNode()) || isIndirect) {
2967 AddressRegisters.
insert(ARM::R12);
2970 AddressRegisters.
erase(
AL.getLocReg());
2971 if (AddressRegisters.
empty()) {
2972 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2991 <<
" (guaranteed tail-call CC)\n");
2992 return CalleeCC == CallerCC;
2997 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2999 if (isCalleeStructRet != isCallerStructRet) {
3015 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
3016 TT.isOSBinFormatMachO())) {
3025 getEffectiveCallingConv(CalleeCC, isVarArg),
3026 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
3034 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
3035 if (CalleeCC != CallerCC) {
3036 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
3037 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
3056 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
3075 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
3084 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
3097 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
3100 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
3104 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
3131 bool isLittleEndian = Subtarget->
isLittle();
3143 "secure entry function would return value through pointer",
3148 for (
unsigned i = 0, realRVLocIdx = 0;
3150 ++i, ++realRVLocIdx) {
3154 SDValue Arg = OutVals[realRVLocIdx];
3155 bool ReturnF16 =
false;
3157 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
3190 auto RetVT = Outs[realRVLocIdx].ArgVT;
3212 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3216 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3222 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3234 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3236 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3241 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3285 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3288bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3289 if (
N->getNumValues() != 1)
3291 if (!
N->hasNUsesOfValue(1, 0))
3299 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3301 TCChain =
Copy->getOperand(0);
3315 SDValue UseChain =
U->getOperand(0);
3323 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3331 if (!
Copy->hasOneUse())
3338 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3340 TCChain =
Copy->getOperand(0);
3345 bool HasRet =
false;
3360bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3378 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3394 EVT PtrVT =
Op.getValueType();
3404 if (Subtarget->genExecuteOnly()) {
3406 auto *
T =
CP->getType();
3407 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3417 return LowerGlobalAddress(GA, DAG);
3422 Align CPAlign =
CP->getAlign();
3424 CPAlign = std::max(CPAlign,
Align(4));
3425 if (
CP->isMachineConstantPoolEntry())
3437 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3446 unsigned ARMPCLabelIndex = 0;
3449 const BlockAddress *BA = cast<BlockAddressSDNode>(
Op)->getBlockAddress();
3452 if (!IsPositionIndependent) {
3455 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3466 if (!IsPositionIndependent)
3497ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3500 "This function expects a Darwin target");
3505 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3511 MVT::i32,
DL, Chain, DescAddr,
3535 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3541ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3558 DAG.
getVTList(MVT::i32, MVT::Other), Ops);
3585 const auto *GA = cast<GlobalAddressSDNode>(
Op);
3602 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3629 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3630 return CallResult.first;
3652 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3660 PtrVT, dl, Chain,
Offset,
3662 Chain =
Offset.getValue(1);
3668 PtrVT, dl, Chain,
Offset,
3678 PtrVT, dl, Chain,
Offset,
3694 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3697 return LowerGlobalTLSAddressWindows(
Op, DAG);
3706 return LowerToTLSGeneralDynamicModel(GA, DAG);
3709 return LowerToTLSExecModels(GA, DAG, model);
3718 while (!Worklist.
empty()) {
3720 if (isa<ConstantExpr>(U)) {
3725 auto *
I = dyn_cast<Instruction>(U);
3726 if (!
I ||
I->getParent()->getParent() !=
F)
3754 auto *GVar = dyn_cast<GlobalVariable>(GV);
3755 if (!GVar || !GVar->hasInitializer() ||
3756 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3757 !GVar->hasLocalLinkage())
3762 auto *
Init = GVar->getInitializer();
3764 Init->needsDynamicRelocation())
3773 auto *CDAInit = dyn_cast<ConstantDataArray>(
Init);
3776 unsigned RequiredPadding = 4 - (
Size % 4);
3777 bool PaddingPossible =
3778 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3783 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3807 if (RequiredPadding != 4) {
3812 while (RequiredPadding--)
3824 ++NumConstpoolPromoted;
3829 if (
const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
3830 if (!(GV = GA->getAliaseeObject()))
3832 if (
const auto *V = dyn_cast<GlobalVariable>(GV))
3833 return V->isConstant();
3834 return isa<Function>(GV);
3842 return LowerGlobalAddressWindows(
Op, DAG);
3844 return LowerGlobalAddressELF(
Op, DAG);
3846 return LowerGlobalAddressDarwin(
Op, DAG);
3854 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
3858 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3871 }
else if (Subtarget->
isROPI() && IsRO) {
3876 }
else if (Subtarget->
isRWPI() && !IsRO) {
3901 if (Subtarget->
useMovt() || Subtarget->genExecuteOnly()) {
3920 "ROPI/RWPI not currently supported for Darwin");
3923 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
3946 "Windows on ARM expects to use movw/movt");
3948 "ROPI/RWPI not currently supported for Windows");
3951 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
3955 else if (!
TM.shouldAssumeDSOLocal(GV))
3979 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3980 Op.getOperand(1), Val);
3997SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
4000 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
4004 case Intrinsic::arm_gnu_eabi_mcount: {
4013 assert(Mask &&
"Missing call preserved mask for calling convention");
4018 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
4022 if (Subtarget->isThumb())
4025 ARM::tBL_PUSHLR, dl, ResultTys,
4026 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
4027 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
4031 {ReturnAddress, Callee, RegisterMask, Chain}),
4040 unsigned IntNo =
Op.getConstantOperandVal(0);
4044 case Intrinsic::thread_pointer: {
4048 case Intrinsic::arm_cls: {
4049 const SDValue &Operand =
Op.getOperand(1);
4050 const EVT VTy =
Op.getValueType();
4061 case Intrinsic::arm_cls64: {
4064 const SDValue &Operand =
Op.getOperand(1);
4065 const EVT VTy =
Op.getValueType();
4088 case Intrinsic::eh_sjlj_lsda: {
4095 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
4105 if (IsPositionIndependent) {
4111 case Intrinsic::arm_neon_vabs:
4114 case Intrinsic::arm_neon_vabds:
4115 if (
Op.getValueType().isInteger())
4117 Op.getOperand(1),
Op.getOperand(2));
4119 case Intrinsic::arm_neon_vabdu:
4121 Op.getOperand(1),
Op.getOperand(2));
4122 case Intrinsic::arm_neon_vmulls:
4123 case Intrinsic::arm_neon_vmullu: {
4124 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
4127 Op.getOperand(1),
Op.getOperand(2));
4129 case Intrinsic::arm_neon_vminnm:
4130 case Intrinsic::arm_neon_vmaxnm: {
4131 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
4134 Op.getOperand(1),
Op.getOperand(2));
4136 case Intrinsic::arm_neon_vminu:
4137 case Intrinsic::arm_neon_vmaxu: {
4138 if (
Op.getValueType().isFloatingPoint())
4140 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
4143 Op.getOperand(1),
Op.getOperand(2));
4145 case Intrinsic::arm_neon_vmins:
4146 case Intrinsic::arm_neon_vmaxs: {
4148 if (!
Op.getValueType().isFloatingPoint()) {
4149 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4152 Op.getOperand(1),
Op.getOperand(2));
4154 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4157 Op.getOperand(1),
Op.getOperand(2));
4159 case Intrinsic::arm_neon_vtbl1:
4161 Op.getOperand(1),
Op.getOperand(2));
4162 case Intrinsic::arm_neon_vtbl2:
4164 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4165 case Intrinsic::arm_mve_pred_i2v:
4166 case Intrinsic::arm_mve_pred_v2i:
4169 case Intrinsic::arm_mve_vreinterpretq:
4172 case Intrinsic::arm_mve_lsll:
4174 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4175 case Intrinsic::arm_mve_asrl:
4177 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4188 if (!Subtarget->hasDataBarrier()) {
4192 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4193 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4204 }
else if (Subtarget->preferISHSTBarriers() &&
4213 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4221 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4223 return Op.getOperand(0);
4226 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4228 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4230 return Op.getOperand(0);
4232 unsigned isData =
Op.getConstantOperandVal(4);
4233 if (Subtarget->isThumb()) {
4235 isRead = ~isRead & 1;
4236 isData = ~isData & 1;
4253 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
4254 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4262 const SDLoc &dl)
const {
4268 RC = &ARM::tGPRRegClass;
4270 RC = &ARM::GPRRegClass;
4284 MVT::i32, dl, Root, FIN,
4305 const Value *OrigArg,
4306 unsigned InRegsParamRecordIdx,
4307 int ArgOffset,
unsigned ArgSize)
const {
4322 unsigned RBegin, REnd;
4332 ArgOffset = -4 * (ARM::R4 - RBegin);
4342 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4351 if (!MemOps.
empty())
4360 unsigned TotalArgRegsSaveSize,
4361 bool ForceMutable)
const {
4372 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4376bool ARMTargetLowering::splitValueIntoRegisterParts(
4378 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4380 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4392SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4394 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4395 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4408SDValue ARMTargetLowering::LowerFormalArguments(
4424 unsigned CurArgIdx = 0;
4436 unsigned ArgRegBegin = ARM::R4;
4443 if (!
Flags.isByVal())
4447 unsigned RBegin, REnd;
4449 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4455 int lastInsIndex = -1;
4459 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4462 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4466 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4468 if (Ins[VA.
getValNo()].isOrigArg()) {
4469 std::advance(CurOrigArg,
4470 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4482 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4489 MVT::f64, dl, Chain, FIN,
4492 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4500 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4504 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4505 RC = &ARM::HPRRegClass;
4506 else if (RegVT == MVT::f32)
4507 RC = &ARM::SPRRegClass;
4508 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4509 RegVT == MVT::v4bf16)
4510 RC = &ARM::DPRRegClass;
4511 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4512 RegVT == MVT::v8bf16)
4513 RC = &ARM::QPRRegClass;
4514 else if (RegVT == MVT::i32)
4516 : &ARM::GPRRegClass;
4562 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4568 if (index != lastInsIndex)
4576 if (
Flags.isByVal()) {
4577 assert(Ins[index].isOrigArg() &&
4578 "Byval arguments cannot be implicit");
4582 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4616 lastInsIndex = index;
4623 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4624 TotalArgRegsSaveSize);
4628 "secure entry function must not be variadic", dl.
getDebugLoc()));
4638 assert(StackAlign &&
"data layout string is missing stack alignment");
4639 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4648 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4657 return CFP->getValueAPF().isPosZero();
4661 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4663 if (
const ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal()))
4664 return CFP->getValueAPF().isPosZero();
4667 Op->getValueType(0) == MVT::f64) {
4682 const SDLoc &dl)
const {
4684 unsigned C = RHSC->getZExtValue();
4750 LHS.getValueType() == MVT::i32 && isa<ConstantSDNode>(RHS) &&
4752 unsigned Mask =
LHS.getConstantOperandVal(1);
4753 auto *RHSC = cast<ConstantSDNode>(
RHS.getNode());
4754 uint64_t RHSV = RHSC->getZExtValue();
4755 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4757 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4772 isa<ConstantSDNode>(RHS) &&
RHS->getAsZExtVal() == 0x80000000U &&
4774 LHS.getConstantOperandVal(1) < 31) {
4775 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4818 bool Signaling)
const {
4819 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4834std::pair<SDValue, SDValue>
4837 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4849 switch (
Op.getOpcode()) {
4862 DAG.
getVTList(
Op.getValueType(), MVT::i32), LHS, RHS)
4901 return std::make_pair(
Value, OverflowCmp);
4912 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4917 EVT VT =
Op.getValueType();
4960 EVT VT =
Op.getValueType();
4964 switch (
Op.getOpcode()) {
4989 EVT VT =
Op.getValueType();
4990 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
5000 switch (
Op->getOpcode()) {
5016 switch (
Op->getOpcode()) {
5035 DAG.
getNode(NewOpcode, dl, MVT::i32,
5046 unsigned Opc =
Cond.getOpcode();
5048 if (
Cond.getResNo() == 1 &&
5056 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5057 EVT VT =
Op.getValueType();
5059 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
5069 dyn_cast<ConstantSDNode>(
Cond.getOperand(0));
5071 dyn_cast<ConstantSDNode>(
Cond.getOperand(1));
5073 if (CMOVTrue && CMOVFalse) {
5079 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5081 False = SelectFalse;
5082 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5088 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5089 Cond.getOperand(3), DAG);
5104 bool &swpCmpOps,
bool &swpVselOps) {
5132 swpCmpOps = !swpCmpOps;
5133 swpVselOps = !swpVselOps;
5156 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5158 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5160 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5195 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5197 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5218 EVT VT =
Op.getValueType();
5225 const SDValue Op2 = isa<ConstantSDNode>(TrueVal1) ? FalseVal1 : TrueVal1;
5240 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5248 if (!isa<ConstantSDNode>(K1) || !isa<ConstantSDNode>(K2))
5251 int64_t Val1 = cast<ConstantSDNode>(K1)->getSExtValue();
5252 int64_t Val2 = cast<ConstantSDNode>(K2)->getSExtValue();
5253 int64_t PosVal = std::max(Val1, Val2);
5254 int64_t NegVal = std::min(Val1, Val2);
5300 SDValue KTmp = isa<ConstantSDNode>(TrueVal) ? TrueVal : FalseVal;
5301 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5306 if (*K != KTmp || V != VTmp)
5317bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5321 return !Subtarget->hasFP64();
5323 return !Subtarget->hasFullFP16();
5328 EVT VT =
Op.getValueType();
5332 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->
isThumb2())
5344 if (VT == MVT::i32 &&
5364 if (
Op.getValueType().isInteger()) {
5372 LHS.getValueType() ==
RHS.getValueType()) {
5373 EVT VT =
LHS.getValueType();
5379 Shift = DAG.
getNOT(dl, Shift, VT);
5385 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5386 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5389 unsigned Opcode = 0;
5391 if (TVal == ~FVal) {
5393 }
else if (TVal == ~FVal + 1) {
5395 }
else if (TVal + 1 == FVal) {
5397 }
else if (TVal == FVal + 1) {
5427 SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl);
5429 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5433 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5438 if (!
RHS.getNode()) {
5444 if (
LHS.getValueType() == MVT::i32) {
5456 TrueVal.getValueType() == MVT::f32 ||
5457 TrueVal.getValueType() == MVT::f64)) {
5467 SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl);
5471 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5483 (
TrueVal.getValueType() == MVT::f16 ||
5484 TrueVal.getValueType() == MVT::f32 ||
5485 TrueVal.getValueType() == MVT::f64)) {
5486 bool swpCmpOps =
false;
5487 bool swpVselOps =
false;
5501 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5504 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5514 if (!
N->hasOneUse())
5517 if (!
N->getNumValues())
5519 EVT VT =
Op.getValueType();
5520 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5537 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5538 Ld->getPointerInfo(), Ld->getAlign(),
5539 Ld->getMemOperand()->getFlags());
5557 DAG.
getLoad(MVT::i32, dl, Ld->getChain(),
Ptr, Ld->getPointerInfo(),
5558 Ld->getAlign(), Ld->getMemOperand()->getFlags());
5560 EVT PtrType =
Ptr.getValueType();
5563 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5564 Ld->getPointerInfo().getWithOffset(4),
5566 Ld->getMemOperand()->getFlags());
5584 bool LHSSeenZero =
false;
5586 bool RHSSeenZero =
false;
5588 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5599 if (
LHS.getValueType() == MVT::f32) {
5604 SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl);
5617 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5632 unsigned Opc =
Cond.getOpcode();
5635 if (
Cond.getResNo() == 1 &&
5645 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5668 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5673 if (!
RHS.getNode()) {
5681 unsigned Opc =
LHS.getOpcode();
5695 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5709 if (
LHS.getValueType() == MVT::i32) {
5711 SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl);
5718 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5749 if (Subtarget->
isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5755 Addr,
Op.getOperand(2), JTI);
5761 Chain =
Addr.getValue(1);
5768 Chain =
Addr.getValue(1);
5774 EVT VT =
Op.getValueType();
5777 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5778 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5786 const EVT OpTy =
Op.getOperand(0).getValueType();
5787 if (OpTy == MVT::v4f32)
5789 else if (OpTy == MVT::v4f16 && HasFullFP16)
5791 else if (OpTy == MVT::v8f16 && HasFullFP16)
5796 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5799 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5804 EVT VT =
Op.getValueType();
5808 bool IsStrict =
Op->isStrictFPOpcode();
5809 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5811 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5821 MakeLibCallOptions CallOptions;
5824 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5825 CallOptions, Loc, Chain);
5835 Loc,
Op.getValueType(), SrcVal);
5844 EVT VT =
Op.getValueType();
5845 EVT ToVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
5846 EVT FromVT =
Op.getOperand(0).getValueType();
5848 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5850 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5851 Subtarget->hasFP64())
5853 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5854 Subtarget->hasFullFP16())
5856 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5857 Subtarget->hasMVEFloatOps())
5859 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5860 Subtarget->hasMVEFloatOps())
5863 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5880 EVT VT =
Op.getValueType();
5883 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5889 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5890 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5891 "Invalid type for custom lowering!");
5896 if (VT == MVT::v4f32)
5897 DestVecType = MVT::v4i32;
5898 else if (VT == MVT::v4f16 && HasFullFP16)
5899 DestVecType = MVT::v4i16;
5900 else if (VT == MVT::v8f16 && HasFullFP16)
5901 DestVecType = MVT::v8i16;
5907 switch (
Op.getOpcode()) {
5919 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5924 EVT VT =
Op.getValueType();
5927 if (isUnsupportedFloatingType(VT)) {
5935 MakeLibCallOptions CallOptions;
5937 CallOptions,
SDLoc(
Op)).first;
5948 EVT VT =
Op.getValueType();
5952 bool UseNEON = !InGPR && Subtarget->hasNEON();
5959 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5966 if (SrcVT == MVT::f32) {
5972 }
else if (VT == MVT::f32)
5988 if (VT == MVT::f32) {
6000 if (SrcVT == MVT::f64)
6009 if (VT == MVT::f32) {
6030 EVT VT =
Op.getValueType();
6032 unsigned Depth =
Op.getConstantOperandVal(0);
6034 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
6053 EVT VT =
Op.getValueType();
6055 unsigned Depth =
Op.getConstantOperandVal(0);
6069 .
Case(
"sp", ARM::SP)
6080 assert(
N->getValueType(0) == MVT::i64
6081 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6084 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6124 const APInt &APIntIndex = Index->getAPIntValue();
6126 NewIndex *= APIntIndex;
6155 EVT SrcVT =
Op.getValueType();
6156 EVT DstVT =
N->getValueType(0);
6158 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6159 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6163 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6164 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6165 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6172 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6225 EVT VT =
Op.getValueType();
6268 EVT VT =
Op.getValueType();
6310 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6362 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6390 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6420 EVT VT =
N->getValueType(0);
6421 if (VT.
isVector() && ST->hasNEON()) {
6430 if (ElemTy == MVT::i8) {
6438 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6453 if (ElemTy == MVT::i64) {
6466 if (!ST->hasV6T2Ops())
6475 EVT VT =
N->getValueType(0);
6478 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6479 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6480 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6481 "Unexpected type for custom ctpop lowering");
6489 unsigned EltSize = 8;
6512 Op =
Op.getOperand(0);
6514 APInt SplatBits, SplatUndef;
6515 unsigned SplatBitSize;
6518 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6520 SplatBitSize > ElementBits)
6531 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6535 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6546 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6551 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6552 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6561 EVT VT =
N->getValueType(0);
6583 "unexpected vector shift opcode");
6585 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6586 unsigned VShiftOpc =
6588 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6594 EVT ShiftVT =
N->getOperand(1).getValueType();
6597 unsigned VShiftOpc =
6599 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6604 EVT VT =
N->getValueType(0);
6613 "Unknown shift to lower!");
6615 unsigned ShOpc =
N->getOpcode();
6616 if (ST->hasMVEIntegerOps()) {
6646 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6660 if (ST->isThumb1Only())
6665 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6681 bool Invert =
false;
6688 EVT VT =
Op.getValueType();
6689 ISD::CondCode SetCCOpcode = cast<CondCodeSDNode>(CC)->get();
6696 assert(ST->hasMVEIntegerOps() &&
6697 "No hardware support for integer vector comparison!");
6699 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6724 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6734 switch (SetCCOpcode) {
6738 if (ST->hasMVEFloatOps()) {
6741 Invert =
true; [[fallthrough]];
6746 case ISD::SETLT: Swap =
true; [[fallthrough]];
6750 case ISD::SETLE: Swap =
true; [[fallthrough]];
6766 Result = DAG.
getNOT(dl, Result, VT);
6769 case ISD::SETUO: Invert =
true; [[fallthrough]];
6778 Result = DAG.
getNOT(dl, Result, VT);
6784 switch (SetCCOpcode) {
6787 if (ST->hasMVEIntegerOps()) {
6790 Invert =
true; [[fallthrough]];
6793 case ISD::SETLT: Swap =
true; [[fallthrough]];
6795 case ISD::SETLE: Swap =
true; [[fallthrough]];
6820 Result = DAG.
getNOT(dl, Result, VT);
6854 Result = DAG.
getNOT(dl, Result, VT);
6866 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6893 unsigned OpCmode, Imm;
6904 switch (SplatBitSize) {
6909 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6912 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6917 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6918 if ((SplatBits & ~0xff) == 0) {
6924 if ((SplatBits & ~0xff00) == 0) {
6927 Imm = SplatBits >> 8;
6937 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6938 if ((SplatBits & ~0xff) == 0) {
6944 if ((SplatBits & ~0xff00) == 0) {
6947 Imm = SplatBits >> 8;
6950 if ((SplatBits & ~0xff0000) == 0) {
6953 Imm = SplatBits >> 16;
6956 if ((SplatBits & ~0xff000000) == 0) {
6959 Imm = SplatBits >> 24;
6966 if ((SplatBits & ~0xffff) == 0 &&
6967 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6970 Imm = SplatBits >> 8;
6978 if ((SplatBits & ~0xffffff) == 0 &&
6979 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6982 Imm = SplatBits >> 16;
6998 unsigned ImmMask = 1;
7000 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
7001 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
7003 }
else if ((SplatBits & BitMask) != 0) {
7012 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
7026 EVT VT =
Op.getValueType();
7027 bool IsDouble = (VT == MVT::f64);
7033 if (
ST->genExecuteOnly()) {
7035 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
7036 "Unexpected architecture");
7059 if (!
ST->hasVFP3Base())
7064 if (IsDouble && !Subtarget->hasFP64())
7071 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7089 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7098 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7152 unsigned ExpectedElt = Imm;
7153 for (
unsigned i = 1; i < NumElts; ++i) {
7157 if (ExpectedElt == NumElts)
7160 if (M[i] < 0)
continue;
7161 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7169 bool &ReverseVEXT,
unsigned &Imm) {
7171 ReverseVEXT =
false;
7182 unsigned ExpectedElt = Imm;
7183 for (
unsigned i = 1; i < NumElts; ++i) {
7187 if (ExpectedElt == NumElts * 2) {
7192 if (M[i] < 0)
continue;
7193 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7208 return VT == MVT::v8i8 && M.size() == 8;
7213 if (Mask.size() == Elements * 2)
7214 return Index / Elements;
7215 return Mask[Index] == 0 ? 0 : 1;
7245 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7253 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7255 for (
unsigned j = 0; j < NumElts; j += 2) {
7256 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7257 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7262 if (M.size() == NumElts*2)
7277 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7280 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7282 for (
unsigned j = 0; j < NumElts; j += 2) {
7283 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7284 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7289 if (M.size() == NumElts*2)
7309 if (M.size() != NumElts && M.size() != NumElts*2)
7312 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7314 for (
unsigned j = 0; j < NumElts; ++j) {
7315 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7320 if (M.size() == NumElts*2)
7339 if (M.size() != NumElts && M.size() != NumElts*2)
7342 unsigned Half = NumElts / 2;
7343 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7345 for (
unsigned j = 0; j < NumElts; j += Half) {
7346 unsigned Idx = WhichResult;
7347 for (
unsigned k = 0; k < Half; ++k) {
7348 int MIdx = M[i + j + k];
7349 if (MIdx >= 0 && (
unsigned) MIdx !=
Idx)
7356 if (M.size() == NumElts*2)
7380 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7383 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7385 unsigned Idx = WhichResult * NumElts / 2;
7386 for (
unsigned j = 0; j < NumElts; j += 2) {
7387 if ((M[i+j] >= 0 && (
unsigned) M[i+j] !=
Idx) ||
7388 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] !=
Idx + NumElts))
7394 if (M.size() == NumElts*2)
7413 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7416 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7418 unsigned Idx = WhichResult * NumElts / 2;
7419 for (
unsigned j = 0; j < NumElts; j += 2) {
7420 if ((M[i+j] >= 0 && (
unsigned) M[i+j] !=
Idx) ||
7421 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] !=
Idx))
7427 if (M.size() == NumElts*2)
7440 unsigned &WhichResult,
7443 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7445 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7447 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7465 if (NumElts != M.size())
7469 for (
unsigned i = 0; i != NumElts; ++i)
7470 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7479 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7487 int Ofs = Top ? 1 : 0;
7488 int Upper = SingleSource ? 0 : NumElts;
7489 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7490 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7492 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7501 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7510 unsigned Offset = Top ? 0 : 1;
7511 unsigned N = SingleSource ? 0 : NumElts;
7512 for (
unsigned i = 0; i < NumElts; i += 2) {
7513 if (M[i] >= 0 && M[i] != (
int)i)
7515 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7524 if (NumElts != M.size())
7532 unsigned Off0 = rev ? NumElts / 2 : 0;
7533 unsigned Off1 = rev ? 0 : NumElts / 2;
7534 for (
unsigned i = 0; i < NumElts; i += 2) {
7535 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7537 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7553 if (!ST->hasMVEFloatOps())
7558 if (VT != MVT::v8f16)
7579 for (
unsigned i = 1; i < 4; i++) {
7606 if (!ST->hasMVEFloatOps())
7611 if (VT != MVT::v4f32)
7627 for (
unsigned i = 1; i < 4; i++) {
7648 if (!isa<ConstantSDNode>(
N))
7650 Val =
N->getAsZExtVal();
7652 if (ST->isThumb1Only()) {
7653 if (Val <= 255 || ~Val <= 255)
7665 EVT VT =
Op.getValueType();
7667 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7671 unsigned BitsPerBool;
7675 }
else if (NumElts == 4) {
7678 }
else if (NumElts == 8) {
7681 }
else if (NumElts == 16) {
7690 if (!isa<ConstantSDNode>(FirstOp) &&
7692 return U.get().isUndef() || U.get() == FirstOp;
7700 unsigned Bits32 = 0;
7701 for (
unsigned i = 0; i < NumElts; ++i) {
7703 if (!isa<ConstantSDNode>(V) && !V.isUndef())
7705 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7707 Bits32 |= BoolMask << (i * BitsPerBool);
7713 for (
unsigned i = 0; i < NumElts; ++i) {
7715 if (isa<ConstantSDNode>(V) || V.isUndef())
7726 if (!ST->hasMVEIntegerOps())
7730 EVT VT =
Op.getValueType();
7740 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7744 for (
unsigned I = 2;
I < NumElts;
I++) {
7760 switch (
N->getOpcode()) {
7771 return N->getOperand(1).getNode() ==
Op;
7773 switch (
N->getConstantOperandVal(0)) {
7774 case Intrinsic::arm_mve_add_predicated:
7775 case Intrinsic::arm_mve_mul_predicated:
7776 case Intrinsic::arm_mve_qadd_predicated:
7777 case Intrinsic::arm_mve_vhadd:
7778 case Intrinsic::arm_mve_hadd_predicated:
7779 case Intrinsic::arm_mve_vqdmulh:
7780 case Intrinsic::arm_mve_qdmulh_predicated:
7781 case Intrinsic::arm_mve_vqrdmulh:
7782 case Intrinsic::arm_mve_qrdmulh_predicated:
7783 case Intrinsic::arm_mve_vqdmull:
7784 case Intrinsic::arm_mve_vqdmull_predicated:
7786 case Intrinsic::arm_mve_sub_predicated:
7787 case Intrinsic::arm_mve_qsub_predicated:
7788 case Intrinsic::arm_mve_vhsub:
7789 case Intrinsic::arm_mve_hsub_predicated:
7790 return N->getOperand(2).getNode() ==
Op;
7805 EVT VT =
Op.getValueType();
7813 APInt SplatBits, SplatUndef;
7814 unsigned SplatBitSize;
7816 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7823 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7825 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7826 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7827 : SplatBitSize == 16 ? MVT::v8i16
7834 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7835 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7840 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7848 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7850 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7858 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7868 if (
ST->hasMVEIntegerOps() &&
7869 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7870 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7871 : SplatBitSize == 16 ? MVT::v8i16
7888 bool isOnlyLowElement =
true;
7889 bool usesOnlyOneValue =
true;
7890 bool hasDominantValue =
false;
7897 for (
unsigned i = 0; i < NumElts; ++i) {
7902 isOnlyLowElement =
false;
7903 if (!isa<ConstantFPSDNode>(V) && !isa<ConstantSDNode>(V))
7906 unsigned &Count = ValueCounts[
V];
7909 if (++Count > (NumElts / 2)) {
7910 hasDominantValue =
true;
7914 if (ValueCounts.
size() != 1)
7915 usesOnlyOneValue =
false;
7916 if (!
Value.getNode() && !ValueCounts.
empty())
7919 if (ValueCounts.
empty())
7931 if (hasDominantValue && EltSize <= 32) {
7942 (constIndex = dyn_cast<ConstantSDNode>(
Value->getOperand(1)))) {
7947 if (VT !=
Value->getOperand(0).getValueType()) {
7960 if (!usesOnlyOneValue) {
7963 for (
unsigned I = 0;
I < NumElts; ++
I) {
7978 assert(FVT == MVT::f32 || FVT == MVT::f16);
7979 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7980 for (
unsigned i = 0; i < NumElts; ++i)
7985 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7989 if (usesOnlyOneValue) {
8016 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
8036 if (EltSize >= 32) {
8042 for (
unsigned i = 0; i < NumElts; ++i)
8056 for (
unsigned i = 0 ; i < NumElts; ++i) {
8075 EVT VT =
Op.getValueType();
8078 struct ShuffleSourceInfo {
8080 unsigned MinElt = std::numeric_limits<unsigned>::max();
8081 unsigned MaxElt = 0;
8091 int WindowScale = 1;
8093 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8095 bool operator ==(
SDValue OtherVec) {
return Vec == OtherVec; }
8101 for (
unsigned i = 0; i < NumElts; ++i) {
8109 }
else if (!isa<ConstantSDNode>(
V.getOperand(1))) {
8116 SDValue SourceVec =
V.getOperand(0);
8118 if (Source == Sources.
end())
8122 unsigned EltNo =
V.getConstantOperandVal(1);
8129 if (Sources.
size() > 2)
8135 for (
auto &Source : Sources) {
8136 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8137 if (SrcEltTy.
bitsLT(SmallestEltTy))
8138 SmallestEltTy = SrcEltTy;
8140 unsigned ResMultiplier =
8148 for (
auto &Src : Sources) {
8149 EVT SrcVT = Src.ShuffleVec.getValueType();
8153 if (SrcVTSize == VTSize)
8162 if (SrcVTSize < VTSize) {
8163 if (2 * SrcVTSize != VTSize)
8169 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8173 if (SrcVTSize != 2 * VTSize)
8176 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8181 if (Src.MinElt >= NumSrcElts) {
8186 Src.WindowBase = -NumSrcElts;
8187 }
else if (Src.MaxElt < NumSrcElts) {
8204 Src.WindowBase = -Src.MinElt;
8211 for (
auto &Src : Sources) {
8212 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8213 if (SrcEltTy == SmallestEltTy)
8218 Src.WindowBase *= Src.WindowScale;
8223 for (
auto Src : Sources)
8224 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8232 if (
Entry.isUndef())
8236 int EltNo = cast<ConstantSDNode>(
Entry.getOperand(1))->getSExtValue();
8241 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8244 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8248 int *LaneMask = &
Mask[i * ResMultiplier];
8250 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8251 ExtractBase += NumElts * (Src - Sources.begin());
8252 for (
int j = 0;
j < LanesDefined; ++
j)
8253 LaneMask[j] = ExtractBase + j;
8259 assert(Sources.size() <= 2 &&
"Too many sources!");
8262 for (
unsigned i = 0; i < Sources.size(); ++i)
8291 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8311 unsigned PFIndexes[4];
8312 for (
unsigned i = 0; i != 4; ++i) {
8316 PFIndexes[i] = M[i];
8320 unsigned PFTableIndex =
8321 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8323 unsigned Cost = (PFEntry >> 30);
8329 bool ReverseVEXT, isV_UNDEF;
8330 unsigned Imm, WhichResult;
8333 if (EltSize >= 32 ||
8340 else if (Subtarget->hasNEON() &&
8345 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8348 else if (Subtarget->hasMVEIntegerOps() &&
8352 else if (Subtarget->hasMVEIntegerOps() &&
8366 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8367 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8368 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8371 if (LHSID == (1*9+2)*9+3)
return LHS;
8372 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8429 for (
int I : ShuffleMask)
8442 EVT VT =
Op.getValueType();
8444 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8445 "Expect an v8i16/v16i8 type");
8451 std::vector<int> NewMask;
8455 NewMask.push_back(i);
8495 if (VT != MVT::v16i1)
8511 EVT VT =
Op.getValueType();
8515 assert(ST->hasMVEIntegerOps() &&
8516 "No support for vector shuffle of boolean predicates");
8542 "Expected identical vector type in expanded i1 shuffle!");
8546 PredAsVector2, ShuffleMask);
8551 if (VT == MVT::v2i1) {
8568 EVT VT =
Op.getValueType();
8572 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8573 "Unexpected vector type");
8575 int QuarterSize = NumElts / 4;
8584 for (
int i = 0; i <
Length; i++) {
8585 if (ShuffleMask[Start + i] >= 0) {
8586 if (ShuffleMask[Start + i] %
Length != i)
8588 MovIdx = ShuffleMask[Start + i] /
Length;
8596 for (
int i = 1; i <
Length; i++) {
8597 if (ShuffleMask[Start + i] >= 0 &&
8598 (ShuffleMask[Start + i] /
Length != MovIdx ||
8599 ShuffleMask[Start + i] %
Length != i))
8605 for (
int Part = 0; Part < 4; ++Part) {
8607 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8611 Input =
Op->getOperand(1);
8621 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8626 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8628 for (
int Part = 0; Part < 4; ++Part)
8629 for (
int i = 0; i < QuarterSize; i++)
8631 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8633 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8636 for (
int Part = 0; Part < 4; ++Part)
8652 EVT VT =
Op.getValueType();
8664 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8668 if (Mask[i] != i + BaseOffset) {
8669 if (OffElement == -1)
8675 return NonUndef > 2 && OffElement != -1;
8679 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8681 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8692 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8703 EVT VT =
Op.getValueType();
8707 if (ST->hasMVEIntegerOps() && EltSize == 1)
8718 if (EltSize <= 32) {
8722 if (Lane == -1) Lane = 0;
8733 bool IsScalarToVector =
true;
8736 IsScalarToVector =
false;
8739 if (IsScalarToVector)
8746 bool ReverseVEXT =
false;
8748 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8772 unsigned WhichResult = 0;
8773 bool isV_UNDEF =
false;
8774 if (ST->hasNEON()) {
8776 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8783 if (ST->hasMVEIntegerOps()) {
8818 }) &&
"Unexpected shuffle index into UNDEF operand!");
8821 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8824 assert((WhichResult == 0) &&
8825 "In-place shuffle of concat can only have one result!");
8834 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8838 for (
bool Top : {
false,
true}) {
8839 for (
bool SingleSource : {
false,
true}) {
8840 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8845 SingleSource ? V1 : V2);
8861 unsigned PFIndexes[4];
8862 for (
unsigned i = 0; i != 4; ++i) {
8863 if (ShuffleMask[i] < 0)
8866 PFIndexes[i] = ShuffleMask[i];
8870 unsigned PFTableIndex =
8871 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8873 unsigned Cost = (PFEntry >> 30);
8879 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8880 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8890 if (EltSize >= 32) {
8898 for (
unsigned i = 0; i < NumElts; ++i) {
8899 if (ShuffleMask[i] < 0)
8903 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8911 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8915 if (ST->hasNEON() && VT == MVT::v8i8)
8919 if (ST->hasMVEIntegerOps())
8928 EVT VecVT =
Op.getOperand(0).getValueType();
8931 assert(ST->hasMVEIntegerOps() &&
8932 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8936 unsigned Lane =
Op.getConstantOperandVal(2);
8937 unsigned LaneWidth =
8939 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8951 if (!isa<ConstantSDNode>(Lane))
8957 if (Subtarget->hasMVEIntegerOps() &&
8958 Op.getValueType().getScalarSizeInBits() == 1)
8982 IVecIn, IElt, Lane);
8991 EVT VecVT =
Op.getOperand(0).getValueType();
8994 assert(ST->hasMVEIntegerOps() &&
8995 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8999 unsigned Lane =
Op.getConstantOperandVal(1);
9000 unsigned LaneWidth =
9011 if (!isa<ConstantSDNode>(Lane))
9031 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
9032 "Unexpected custom CONCAT_VECTORS lowering");
9034 "Unexpected custom CONCAT_VECTORS lowering");
9035 assert(ST->hasMVEIntegerOps() &&
9036 "CONCAT_VECTORS lowering only supported for MVE");
9040 EVT Op2VT = V2.getValueType();
9041 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9042 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9043 "Unexpected i1 concat operations!");
9056 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9070 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9071 EVT NewVT = NewV.getValueType();
9072 EVT ConcatVT = ConVec.getValueType();
9073 unsigned ExtScale = 1;
9074 if (NewVT == MVT::v2f64) {
9088 ConVec = ExtractInto(NewV1, ConVec, j);
9089 ConVec = ExtractInto(NewV2, ConVec, j);
9099 while (ConcatOps.
size() > 1) {
9100 for (
unsigned I = 0, E = ConcatOps.
size();
I != E;
I += 2) {
9103 ConcatOps[
I / 2] = ConcatPair(V1, V2);
9107 return ConcatOps[0];
9112 EVT VT =
Op->getValueType(0);
9119 "unexpected CONCAT_VECTORS");
9140 EVT VT =
Op.getValueType();
9146 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9147 assert(ST->hasMVEIntegerOps() &&
9148 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9158 EVT SubVT = MVT::v4i32;
9160 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9175 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9191 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9192 EVT VT =
N->getValueType(0);
9193 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9194 "Expected a vector i1 type!");
9196 EVT FromVT =
Op.getValueType();
9207 if (!Subtarget->hasMVEIntegerOps())
9210 EVT ToVT =
N->getValueType(0);
9253 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9255 EVT FromVT =
N->getOperand(0).getValueType();
9256 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9267 if (!Subtarget->hasMVEIntegerOps())
9272 EVT ToVT =
N->getValueType(0);
9273 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9276 EVT FromVT =
Op.getValueType();
9277 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9288 SDValue Ext1 = Ext.getValue(1);
9291 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9292 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9304 EVT VT =
N->getValueType(0);
9306 SDNode *BVN =
N->getOperand(0).getNode();
9311 unsigned HiElt = 1 - LoElt;
9316 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9332 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9333 SDNode *Elt =
N->getOperand(i).getNode();
9336 unsigned HalfSize = EltSize / 2;
9338 if (!
isIntN(HalfSize,
C->getSExtValue()))
9341 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9380 switch (OrigSimpleTy) {
9396 unsigned ExtOpcode) {
9419 if (ExtendedTy == LD->getMemoryVT())
9420 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9421 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9422 LD->getMemOperand()->getFlags());
9428 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9429 LD->getMemoryVT(), LD->getAlign(),
9430 LD->getMemOperand()->getFlags());
9443 N->getOperand(0)->getValueType(0),
9449 "Expected extending load");
9455 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9464 SDNode *BVN =
N->getOperand(0).getNode();
9466 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9474 EVT VT =
N->getValueType(0);
9480 for (
unsigned i = 0; i != NumElts; ++i) {
9481 const APInt &CInt =
N->getConstantOperandAPInt(i);
9490 unsigned Opcode =
N->getOpcode();
9492 SDNode *N0 =
N->getOperand(0).getNode();
9493 SDNode *N1 =
N->getOperand(1).getNode();
9501 unsigned Opcode =
N->getOpcode();
9503 SDNode *N0 =
N->getOperand(0).getNode();
9504 SDNode *N1 =
N->getOperand(1).getNode();
9514 EVT VT =
Op.getValueType();
9516 "unexpected type for custom-lowering ISD::MUL");
9517 SDNode *N0 =
Op.getOperand(0).getNode();
9518 SDNode *N1 =
Op.getOperand(1).getNode();
9519 unsigned NewOpc = 0;
9523 if (isN0SExt && isN1SExt)
9528 if (isN0ZExt && isN1ZExt)
9530 else if (isN1SExt || isN1ZExt) {
9547 if (VT == MVT::v2i64)
9564 "unexpected types for extended operands to VMULL");
9565 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9600 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9634 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9637 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9658 EVT VT =
Op.getValueType();
9659 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9660 "unexpected type for custom-lowering ISD::SDIV");
9667 if (VT == MVT::v8i8) {
9695 EVT VT =
Op.getValueType();
9696 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9697 "unexpected type for custom-lowering ISD::UDIV");
9704 if (VT == MVT::v8i8) {
9743 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9746 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9750 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9771 EVT VT =
N->getValueType(0);
9785 Op.getOperand(1), Carry);
9799 Op.getOperand(1), Carry);
9833 if (ShouldUseSRet) {
9841 Entry.IsSExt =
false;
9842 Entry.IsZExt =
false;
9843 Entry.IsSRet =
true;
9844 Args.push_back(Entry);
9848 Args.emplace_back(Arg, ArgTy);
9851 (ArgVT == MVT::f64) ? RTLIB::SINCOS_STRET_F64 : RTLIB::SINCOS_STRET_F32;
9861 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
9864 return CallResult.first;
9883 EVT VT =
Op.getValueType();
9884 assert((VT == MVT::i32 || VT == MVT::i64) &&
9885 "unexpected type for custom lowering DIV");
9891 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9893 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9900 for (
auto AI : {1, 0}) {
9902 Args.emplace_back(Operand,
9906 CallLoweringInfo CLI(DAG);
9910 ES, std::move(Args));
9920ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9928 const bool MinSize =
ST.hasMinSize();
9929 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9930 :
ST.hasDivideInARMMode();
9934 if (
N->getOperand(0).getValueType().isVector())
9939 if (!(MinSize && HasDivide))
9952 if (Divisor.
sgt(128))
9960 assert(
Op.getValueType() == MVT::i32 &&
9961 "unexpected type for custom lowering DIV");
9967 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9973 if (
N->getValueType(0) == MVT::i32)
9981void ARMTargetLowering::ExpandDIV_Windows(
9986 assert(
Op.getValueType() == MVT::i64 &&
9987 "unexpected type for custom lowering DIV");
10004 EVT MemVT = LD->getMemoryVT();
10005 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10006 MemVT == MVT::v16i1) &&
10007 "Expected a predicate type!");
10008 assert(MemVT ==
Op.getValueType());
10010 "Expected a non-extending load");
10011 assert(LD->isUnindexed() &&
"Expected a unindexed load");
10025 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
10027 LD->getMemOperand());
10034 if (MemVT != MVT::v16i1)
10043 EVT MemVT =
LD->getMemoryVT();
10044 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10046 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10052 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10062 EVT MemVT = ST->getMemoryVT();
10063 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10064 MemVT == MVT::v16i1) &&
10065 "Expected a predicate type!");
10066 assert(MemVT == ST->getValue().getValueType());
10067 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10068 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10073 SDValue Build = ST->getValue();
10074 if (MemVT != MVT::v16i1) {
10093 ST->getChain(), dl, GRP, ST->getBasePtr(),
10095 ST->getMemOperand());
10101 EVT MemVT = ST->getMemoryVT();
10102 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10104 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10120 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10121 MemVT, ST->getMemOperand());
10122 }
else if (Subtarget->hasMVEIntegerOps() &&
10123 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10124 MemVT == MVT::v16i1))) {
10139 MVT VT =
Op.getSimpleValueType();
10141 SDValue PassThru =
N->getPassThru();
10152 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10153 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10154 N->getExtensionType(),
N->isExpandingLoad());
10159 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10166 if (!ST->hasMVEIntegerOps())
10170 unsigned BaseOpcode = 0;
10171 switch (
Op->getOpcode()) {
10187 unsigned NumActiveLanes = NumElts;
10189 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10190 NumActiveLanes == 2) &&
10191 "Only expected a power 2 vector size");
10195 while (NumActiveLanes > 4) {
10198 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10199 NumActiveLanes /= 2;
10203 if (NumActiveLanes == 4) {
10213 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10214 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10215 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10221 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10225 if (EltVT !=
Op->getValueType(0))
10232 if (!ST->hasMVEFloatOps())
10239 if (!ST->hasNEON())
10247 unsigned PairwiseIntrinsic = 0;
10248 switch (
Op->getOpcode()) {
10252 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10255 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10258 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10261 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10267 unsigned NumActiveLanes = NumElts;
10269 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10270 NumActiveLanes == 2) &&
10271 "Only expected a power 2 vector size");
10277 VT =
Lo.getValueType();
10279 NumActiveLanes /= 2;
10283 while (NumActiveLanes > 1) {
10285 NumActiveLanes /= 2;
10292 if (EltVT !=
Op.getValueType()) {
10293 unsigned Extend = 0;
10294 switch (
Op->getOpcode()) {
10306 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10328 SDValue Ops[] = {
N->getOperand(0),
10338 DAG.
getVTList(MVT::i32, MVT::Other), Ops);
10351 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10353 DAG.
getMachineNode(TargetOpcode::REG_SEQUENCE, dl, MVT::Untyped, Ops), 0);
10357 SDLoc dl(V.getNode());
10358 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10368 assert(
N->getValueType(0) == MVT::i64 &&
10369 "AtomicCmpSwap on types less than 64 should be legal");
10378 ARM::CMP_SWAP_64,
SDLoc(
N),
10379 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other), Ops);
10398 EVT VT =
Op.getValueType();
10407 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10409 Chain, IsSignaling);
10410 if (!
RHS.getNode()) {
10425 SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl, IsSignaling);
10426 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10428 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10429 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10445 MakeLibCallOptions CallOptions;
10446 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10449 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10480 Sub1Result, Sub1Result, Flags1);
10495 if (
Op.getValueType() != MVT::i32)
10518 bool CanUseAdd =
false;
10559 GTCondValue, Flags);
10564 LTCondValue, Flags);
10566 if (
Op.getValueType() != MVT::i32)
10574 switch (
Op.getOpcode()) {
10606 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10610 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10611 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10633 return LowerSET_FPMODE(
Op, DAG);
10635 return LowerRESET_FPMODE(
Op, DAG);
10639 return LowerDIV_Windows(
Op, DAG,
true);
10643 return LowerDIV_Windows(
Op, DAG,
false);
10650 return LowerSignedALUO(
Op, DAG);
10653 return LowerUnsignedALUO(
Op, DAG);
10687 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10696 return LowerSPONENTRY(
Op, DAG);
10698 return LowerFP_TO_BF16(
Op, DAG);
10702 return LowerCMP(
Op, DAG);
10708 unsigned IntNo =
N->getConstantOperandVal(0);
10710 if (IntNo == Intrinsic::arm_smlald)
10712 else if (IntNo == Intrinsic::arm_smlaldx)
10714 else if (IntNo == Intrinsic::arm_smlsld)
10716 else if (IntNo == Intrinsic::arm_smlsldx)
10723 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10727 N->getOperand(1),
N->getOperand(2),
10739 switch (
N->getOpcode()) {
10746 Res = ExpandBITCAST(
N, DAG, Subtarget);
10755 Res = LowerREM(
N, DAG);
10759 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10813 "ROPI/RWPI not currently supported with SjLj");
10822 bool isThumb = Subtarget->isThumb();
10823 bool isThumb2 = Subtarget->
isThumb2();
10826 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10832 : &ARM::GPRRegClass;
10850 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10856 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10862 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10880 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10885 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10890 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10895 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10901 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10916 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10922 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10946 : &ARM::GPRnopcRegClass;
10951 unsigned MaxCSNum = 0;
10959 if (!
II.isEHLabel())
10963 if (!MF->hasCallSiteLandingPad(
Sym))
continue;
10966 for (
unsigned Idx : CallSiteIdxs) {
10967 CallSiteNumToLPad[
Idx].push_back(&BB);
10968 MaxCSNum = std::max(MaxCSNum,
Idx);
10975 std::vector<MachineBasicBlock*> LPadList;
10978 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10981 LPadList.push_back(
MBB);
10986 assert(!LPadList.empty() &&
10987 "No landing pad destinations for the dispatch jump table!");
11002 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
11009 MF->insert(MF->end(), DispatchBB);
11010 MF->insert(MF->end(), DispContBB);
11011 MF->insert(MF->end(), TrapBB);
11015 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11022 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11034 unsigned NumLPads = LPadList.size();
11036 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11037 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11043 if (NumLPads < 256) {
11044 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11046 .
addImm(LPadList.size())
11049 Register VReg1 =
MRI->createVirtualRegister(TRC);
11050 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11051 .
addImm(NumLPads & 0xFFFF)
11054 unsigned VReg2 = VReg1;
11055 if ((NumLPads & 0xFFFF0000) != 0) {
11056 VReg2 =
MRI->createVirtualRegister(TRC);
11057 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11063 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11069 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11074 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11075 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11079 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11080 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11087 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11091 }
else if (Subtarget->isThumb()) {
11092 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11093 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11099 if (NumLPads < 256) {
11100 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11107 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11110 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11113 Register VReg1 =
MRI->createVirtualRegister(TRC);
11114 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11118 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11124 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11129 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
11130 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11136 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11137 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11141 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11142 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11152 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11153 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11159 unsigned NewVReg6 = NewVReg5;
11160 if (IsPositionIndependent) {
11161 NewVReg6 =
MRI->createVirtualRegister(TRC);
11162 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11169 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11173 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11174 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11180 if (NumLPads < 256) {
11181 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11185 }
else if (Subtarget->hasV6T2Ops() && isUInt<16>(NumLPads)) {
11186 Register VReg1 =
MRI->createVirtualRegister(TRC);
11187 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11188 .
addImm(NumLPads & 0xFFFF)
11191 unsigned VReg2 = VReg1;
11192 if ((NumLPads & 0xFFFF0000) != 0) {
11193 VReg2 =
MRI->createVirtualRegister(TRC);
11194 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11200 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11207 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11210 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11213 Register VReg1 =
MRI->createVirtualRegister(TRC);
11214 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11219 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11230 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11231 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11236 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11237 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11244 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11245 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11252 if (IsPositionIndependent) {
11253 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11258 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11267 if (SeenMBBs.
insert(CurMBB).second)
11279 while (!Successors.empty()) {
11288 BB->normalizeSuccProbs();
11295 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11296 if (!
II->isCall())
continue;
11300 OI =
II->operands_begin(), OE =
II->operands_end();
11302 if (!OI->isReg())
continue;
11303 DefRegs.
insert(OI->getReg());
11308 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11309 unsigned Reg = SavedRegs[i];
11311 !ARM::tGPRRegClass.contains(Reg) &&
11312 !ARM::hGPRRegClass.contains(Reg))
11314 if (Subtarget->
isThumb1Only() && !ARM::tGPRRegClass.contains(Reg))
11316 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(Reg))
11329 MBBLPad->setIsEHPad(
false);
11332 MI.eraseFromParent();
11345static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11347 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11348 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11350 return LdSize == 4 ? ARM::tLDRi
11351 : LdSize == 2 ? ARM::tLDRHi
11352 : LdSize == 1 ? ARM::tLDRBi : 0;
11354 return LdSize == 4 ? ARM::t2LDR_POST
11355 : LdSize == 2 ? ARM::t2LDRH_POST
11356 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11357 return LdSize == 4 ? ARM::LDR_POST_IMM
11358 : LdSize == 2 ? ARM::LDRH_POST
11359 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11364static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11366 return StSize == 16 ? ARM::VST1q32wb_fixed
11367 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11369 return StSize == 4 ? ARM::tSTRi
11370 : StSize == 2 ? ARM::tSTRHi
11371 : StSize == 1 ? ARM::tSTRBi : 0;
11373 return StSize == 4 ? ARM::t2STR_POST
11374 : StSize == 2 ? ARM::t2STRH_POST
11375 : StSize == 1 ? ARM::t2STRB_POST : 0;
11376 return StSize == 4 ? ARM::STR_POST_IMM
11377 : StSize == 2 ? ARM::STRH_POST
11378 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11385 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11386 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11387 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11388 assert(LdOpc != 0 &&
"Should have a load opcode");
11395 }
else if (IsThumb1) {
11401 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11406 }
else if (IsThumb2) {
11426 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11427 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11428 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11429 assert(StOpc != 0 &&
"Should have a store opcode");
11431 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11436 }
else if (IsThumb1) {
11443 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11448 }
else if (IsThumb2) {
11449 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11455 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11476 unsigned SizeVal =
MI.getOperand(2).getImm();
11477 unsigned Alignment =
MI.getOperand(3).getImm();
11482 unsigned UnitSize = 0;
11487 bool IsThumb2 = Subtarget->
isThumb2();
11488 bool IsThumb = Subtarget->isThumb();
11490 if (Alignment & 1) {
11492 }
else if (Alignment & 2) {
11497 Subtarget->hasNEON()) {
11498 if ((Alignment % 16 == 0) && SizeVal >= 16)
11500 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11509 bool IsNeon = UnitSize >= 8;
11510 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11512 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11513 : UnitSize == 8 ? &ARM::DPRRegClass
11516 unsigned BytesLeft = SizeVal % UnitSize;
11517 unsigned LoopSize = SizeVal - BytesLeft;
11519 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11523 unsigned srcIn = src;
11524 unsigned destIn = dest;
11525 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11526 Register srcOut =
MRI.createVirtualRegister(TRC);
11527 Register destOut =
MRI.createVirtualRegister(TRC);
11528 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11530 IsThumb1, IsThumb2);
11532 IsThumb1, IsThumb2);
11540 for (
unsigned i = 0; i < BytesLeft; i++) {
11541 Register srcOut =
MRI.createVirtualRegister(TRC);
11542 Register destOut =
MRI.createVirtualRegister(TRC);
11543 Register scratch =
MRI.createVirtualRegister(TRC);
11545 IsThumb1, IsThumb2);
11547 IsThumb1, IsThumb2);
11551 MI.eraseFromParent();
11577 MF->
insert(It, loopMBB);
11578 MF->
insert(It, exitMBB);
11581 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11591 Register varEnd =
MRI.createVirtualRegister(TRC);
11593 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11596 }
else if (Subtarget->genExecuteOnly()) {
11597 assert(IsThumb &&
"Non-thumb expected to have used movt");
11602 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11633 Register varLoop =
MRI.createVirtualRegister(TRC);
11634 Register varPhi =
MRI.createVirtualRegister(TRC);
11635 Register srcLoop =
MRI.createVirtualRegister(TRC);
11636 Register srcPhi =
MRI.createVirtualRegister(TRC);
11637 Register destLoop =
MRI.createVirtualRegister(TRC);
11638 Register destPhi =
MRI.createVirtualRegister(TRC);
11646 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11652 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11654 IsThumb1, IsThumb2);
11656 IsThumb1, IsThumb2);
11660 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11668 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11677 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11686 auto StartOfExit = exitMBB->
begin();
11690 unsigned srcIn = srcLoop;
11691 unsigned destIn = destLoop;
11692 for (
unsigned i = 0; i < BytesLeft; i++) {
11693 Register srcOut =
MRI.createVirtualRegister(TRC);
11694 Register destOut =
MRI.createVirtualRegister(TRC);
11695 Register scratch =
MRI.createVirtualRegister(TRC);
11696 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11697 IsThumb1, IsThumb2);
11698 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11699 IsThumb1, IsThumb2);
11704 MI.eraseFromParent();
11716 "__chkstk is only supported on Windows");
11717 assert(Subtarget->
isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11737 switch (
TM.getCodeModel()) {
11779 MI.eraseFromParent();
11803 .
addReg(
MI.getOperand(0).getReg())
11811 MI.eraseFromParent();
11835 if (miI == BB->
end()) {
11837 if (Succ->isLiveIn(ARM::CPSR))
11843 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11855 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11856 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11862 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11863 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11869 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11870 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11873 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11874 .
addUse(TotalIterationsReg)
11881 return TotalIterationsReg;
11892 Register TotalIterationsReg,
bool IsMemcpy) {
11899 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11900 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11901 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11909 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11910 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11911 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11918 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11919 Register RemainingLoopIterationsReg =
11920 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11921 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11922 .
addUse(TotalIterationsReg)
11924 .
addUse(RemainingLoopIterationsReg)
11928 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11929 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11930 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11931 .
addUse(ElementCountReg)
11933 .
addUse(RemainingElementsReg)
11937 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11938 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11939 .
addUse(PredCounterPhiReg)
11944 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11945 .
addUse(PredCounterPhiReg)
11953 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11954 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11963 SrcValueReg = OpSrcReg;
11965 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11976 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11977 .
addUse(LoopCounterPhiReg)
11980 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11981 .
addUse(RemainingLoopIterationsReg)
11994 bool isThumb2 = Subtarget->
isThumb2();
11995 switch (
MI.getOpcode()) {
12002 case ARM::tLDR_postidx: {
12006 .
add(
MI.getOperand(2))
12007 .
add(
MI.getOperand(3))
12008 .
add(
MI.getOperand(4))
12009 .
add(
MI.getOperand(0))
12011 MI.eraseFromParent();
12015 case ARM::MVE_MEMCPYLOOPINST:
12016 case ARM::MVE_MEMSETLOOPINST: {
12046 Register OpDestReg =
MI.getOperand(0).getReg();
12047 Register OpSrcReg =
MI.getOperand(1).getReg();
12048 Register OpSizeReg =
MI.getOperand(2).getReg();
12068 if (TpExit == BB) {
12070 "block containing memcpy/memset Pseudo");
12083 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12085 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12088 Properties.resetNoPHIs();
12100 MI.eraseFromParent();
12110 case ARM::t2STR_preidx:
12111 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12113 case ARM::t2STRB_preidx:
12114 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12116 case ARM::t2STRH_preidx:
12117 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12120 case ARM::STRi_preidx:
12121 case ARM::STRBi_preidx: {
12122 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12123 : ARM::STRB_PRE_IMM;
12125 unsigned Offset =
MI.getOperand(4).getImm();
12133 .
add(
MI.getOperand(0))
12134 .
add(
MI.getOperand(1))
12135 .
add(
MI.getOperand(2))
12137 .
add(
MI.getOperand(5))
12138 .
add(
MI.getOperand(6))
12140 MI.eraseFromParent();
12143 case ARM::STRr_preidx:
12144 case ARM::STRBr_preidx:
12145 case ARM::STRH_preidx: {
12147 switch (
MI.getOpcode()) {
12149 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12150 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12151 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12156 MI.eraseFromParent();
12160 case ARM::tMOVCCr_pseudo: {
12178 F->insert(It, copy0MBB);
12179 F->insert(It, sinkMBB);
12182 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12188 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12204 .
addImm(
MI.getOperand(3).getImm())
12205 .
addReg(
MI.getOperand(4).getReg());
12220 .
addReg(
MI.getOperand(1).getReg())
12222 .
addReg(
MI.getOperand(2).getReg())
12225 MI.eraseFromParent();
12230 case ARM::BCCZi64: {
12236 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12241 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12245 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12251 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12255 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12265 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12274 MI.eraseFromParent();
12278 case ARM::Int_eh_sjlj_setjmp:
12279 case ARM::Int_eh_sjlj_setjmp_nofp:
12280 case ARM::tInt_eh_sjlj_setjmp:
12281 case ARM::t2Int_eh_sjlj_setjmp:
12282 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12285 case ARM::Int_eh_sjlj_setup_dispatch:
12286 EmitSjLjDispatchBlock(
MI, BB);
12309 Fn->
insert(BBI, SinkBB);
12312 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12316 Register ABSSrcReg =
MI.getOperand(1).getReg();
12317 Register ABSDstReg =
MI.getOperand(0).getReg();
12318 bool ABSSrcKIll =
MI.getOperand(1).isKill();
12319 bool isThumb2 = Subtarget->
isThumb2();
12323 Register NewRsbDstReg =
MRI.createVirtualRegister(
12324 isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRRegClass);
12338 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12345 TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)).
addMBB(SinkBB)
12352 TII->get(isThumb2 ? ARM::t2RSBri : ARM::RSBri), NewRsbDstReg)
12361 TII->get(ARM::PHI), ABSDstReg)
12366 MI.eraseFromParent();
12371 case ARM::COPY_STRUCT_BYVAL_I32:
12373 return EmitStructByval(
MI, BB);
12374 case ARM::WIN__CHKSTK:
12375 return EmitLowered__chkstk(
MI, BB);
12376 case ARM::WIN__DBZCHK:
12377 return EmitLowered__dbzchk(
MI, BB);
12393 if (!
Node->hasAnyUseOfValue(0)) {
12394 MI.getOperand(0).setIsDead(
true);
12396 if (!
Node->hasAnyUseOfValue(1)) {
12397 MI.getOperand(1).setIsDead(
true);
12401 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12402 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12403 : &ARM::GPRRegClass);
12410 if (
MI.getOpcode() == ARM::MEMCPY) {
12428 MCID = &
TII->get(NewOpc);
12431 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12432 &&
"converted opcode should be the same except for cc_out"
12433 " (and, on Thumb1, pred)");
12443 MI.addOperand(
MI.getOperand(1));
12444 MI.removeOperand(1);
12448 for (
unsigned i =
MI.getNumOperands(); i--;) {
12450 if (
op.isReg() &&
op.isUse()) {
12453 MI.tieOperands(DefIdx, i);
12467 if (!
MI.hasOptionalDef() || !MCID->
operands()[ccOutIdx].isOptionalDef()) {
12468 assert(!NewOpc &&
"Optional cc_out operand required");
12473 bool definesCPSR =
false;
12474 bool deadCPSR =
false;
12475 for (
unsigned i = MCID->
getNumOperands(), e =
MI.getNumOperands(); i != e;
12479 definesCPSR =
true;
12482 MI.removeOperand(i);
12486 if (!definesCPSR) {
12487 assert(!NewOpc &&
"Optional cc_out operand required");
12490 assert(deadCPSR == !Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12492 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12493 "expect uninitialized optional cc_out operand");
12531 switch (
N->getOpcode()) {
12532 default:
return false;
12534 CC =
N->getOperand(0);
12556 EVT VT =
N->getValueType(0);
12557 CC =
N->getOperand(0);
12604 EVT VT =
N->getValueType(0);
12607 bool SwapSelectOps;
12609 NonConstantVal, DAG))
12615 OtherOp, NonConstantVal);
12621 CCOp, TrueVal, FalseVal);
12645 if (
N->getOpcode() ==
ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12660 if (!
N->getValueType(0).is64BitVector())
12668 EVT VT =
N->getValueType(0);
12707 EVT VT =
N->getValueType(0);
12713 Opcode = Intrinsic::arm_neon_vpaddls;
12715 Opcode = Intrinsic::arm_neon_vpaddlu;
12743 EVT VT =
N->getValueType(0);
12758 unsigned nextIndex = 0;
12826 return DAG.
getNode(ExtOp, dl, VT, tmp);
12857 if (SRA.getOpcode() !=
ISD::SRA) {
12863 if (
auto Const = dyn_cast<ConstantSDNode>(SRA.getOperand(1))) {
12864 if (Const->getZExtValue() != 31)
12869 if (SRA.getOperand(0) !=
Mul)
12873 SDLoc dl(AddcNode);
12874 unsigned Opcode = 0;
12880 Op0 =
Mul.getOperand(0);
12881 Op1 =
Mul.getOperand(1);
12884 Op0 =
Mul.getOperand(0);
12885 Op1 =
Mul.getOperand(1).getOperand(0);
12888 Op0 =
Mul.getOperand(0).getOperand(0);
12889 Op1 =
Mul.getOperand(1);
12892 Op0 =
Mul->getOperand(0).getOperand(0);
12893 Op1 =
Mul->getOperand(1).getOperand(0);
12902 SDValue HiMLALResult(SMLAL.getNode(), 1);
12903 SDValue LoMLALResult(SMLAL.getNode(), 0);
12909 SDValue resNode(AddcNode, 0);
12938 "Expect an ADDE or SUBE");
12942 "ADDE node has the wrong inputs");
12961 "Expect ADDC with two result values. First: i32");
12981 bool IsLeftOperandMUL =
false;
12986 IsLeftOperandMUL =
true;
12997 SDValue *LowAddSub =
nullptr;
13000 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
13003 if (IsLeftOperandMUL)
13004 HiAddSub = &AddeSubeOp1;
13006 HiAddSub = &AddeSubeOp0;
13011 if (AddcSubcOp0 == MULOp.
getValue(0)) {
13012 LoMul = &AddcSubcOp0;
13013 LowAddSub = &AddcSubcOp1;
13015 if (AddcSubcOp1 == MULOp.
getValue(0)) {
13016 LoMul = &AddcSubcOp1;
13017 LowAddSub = &AddcSubcOp0;
13025 if (AddcSubcNode == HiAddSub->getNode() ||
13041 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13055 return SDValue(AddeSubeNode, 0);
13066 DAG.
getVTList(MVT::i32, MVT::i32), Ops);
13076 return SDValue(AddeSubeNode, 0);
13088 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13097 SDNode *UmlalNode =
nullptr;
13122 DAG.
getVTList(MVT::i32, MVT::i32), Ops);
13136 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13141 SDNode* AddcNode =
N->getOperand(2).getNode();
13142 SDNode* AddeNode =
N->getOperand(3).getNode();
13150 {N->getOperand(0), N->getOperand(1),
13151 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13175 int32_t imm =
C->getSExtValue();
13176 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13181 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13196 int64_t imm =
C->getSExtValue();
13207 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13208 N->getOperand(0),
RHS,
N->getOperand(2));
13220 if (!Subtarget->hasMVEIntegerOps())
13233 SetCC =
N->getOperand(0);
13236 CC = cast<CondCodeSDNode>(SetCC->
getOperand(2))->get();
13237 TrueVal =
N->getOperand(1);
13238 FalseVal =
N->getOperand(2);
13240 LHS =
N->getOperand(0);
13241 RHS =
N->getOperand(1);
13242 CC = cast<CondCodeSDNode>(
N->getOperand(4))->get();
13243 TrueVal =
N->getOperand(2);
13244 FalseVal =
N->getOperand(3);
13249 unsigned int Opcode = 0;
13278 switch (TrueVal->getOpcode()) {
13297 if (TrueVal !=
LHS || FalseVal !=
RHS)
13300 EVT LeftType =
LHS->getValueType(0);
13301 EVT RightType =
RHS->getValueType(0);
13304 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13308 if (VectorScalarType != MVT::i32)
13316 if (VectorScalarType != MVT::i32)
13329 EVT VT =
N->getValueType(0);
13337 Shft =
N->getOperand(0);
13343 cast<CondCodeSDNode>(Cmp.getOperand(2))->get() !=
ISD::SETLT ||
13344 Cmp.getOperand(0) !=
N->getOperand(1) ||
13345 Cmp.getOperand(1) !=
N->getOperand(2))
13347 Shft =
N->getOperand(1);
13359 ScalarType = MVT::i8;
13362 case (1 << 15) - 1:
13363 ScalarType = MVT::i16;
13366 case (1ULL << 31) - 1:
13367 ScalarType = MVT::i32;
13398 unsigned LegalLanes = 128 / (ShftAmt + 1);
13422 for (
unsigned I = 0;
I < NumParts; ++
I) {
13439 if (!Subtarget->hasMVEIntegerOps())
13454 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13464 if (!Const || !Const->isOne())
13481 ISD::CondCode CC = cast<CondCodeSDNode>(
N->getOperand(2))->get();
13482 EVT VT =
N->getValueType(0);
13484 if (!Subtarget->hasMVEIntegerOps() ||
13513 Opc = Intrinsic::arm_mve_vctp64;
13516 Opc = Intrinsic::arm_mve_vctp32;
13519 Opc = Intrinsic::arm_mve_vctp16;
13522 Opc = Intrinsic::arm_mve_vctp8;
13576 EVT VT =
N->getValueType(0);
13582 switch (
Op.getOpcode()) {
13599 !isa<ConstantSDNode>(N0) && N1->
hasOneUse()) {
13607 unsigned N0RedOp = 0;
13614 unsigned N1RedOp = 0;
13628 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13630 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13637 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13651 LoadSDNode *Load0 = dyn_cast<LoadSDNode>(N0);
13652 LoadSDNode *Load1 = dyn_cast<LoadSDNode>(N1);
13661 if (!BaseLocDecomp0.getBase() ||
13662 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13663 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13665 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13667 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13677 if (IsBefore < 0) {
13680 }
else if (IsBefore > 0) {
13693 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13703 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13713 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13715 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13722 if (!Subtarget->hasMVEIntegerOps())
13728 EVT VT =
N->getValueType(0);
13733 if (VT != MVT::i64)
13744 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13762 std::tie(Ops[0], Ops[1]) = DAG.
SplitScalar(NA, dl, MVT::i32, MVT::i32);
13764 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13813 "Expected shift op");
13815 SDValue ShiftLHS =
N->getOperand(0);
13839 if (
auto *Const = dyn_cast<ConstantSDNode>(N1->
getOperand(1))) {
13840 if (Const->getAPIntValue().ult(256))
13843 Const->getAPIntValue().sgt(-256))
13859 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13860 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13861 "Expected XOR(SHIFT) pattern");
13864 auto *XorC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
13865 auto *ShiftC = dyn_cast<ConstantSDNode>(
N->getOperand(0).getOperand(1));
13866 if (XorC && ShiftC) {
13867 unsigned MaskIdx, MaskLen;
13868 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13869 unsigned ShiftAmt = ShiftC->getZExtValue();
13870 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13871 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13872 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13873 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13883 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13885 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13886 "Expected shift-shift mask");
13898 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13900 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13905 if (!Subtarget->hasNEON()) {
13924 return Subtarget->hasFP64();
13927 return Subtarget->hasMVEFloatOps();
13956 if (ST->isThumb() && ST->isThumb1Only())
13960 for (
auto *U :
N->users()) {
13961 switch(U->getOpcode()) {
13974 if (isa<ConstantSDNode>(U->getOperand(0)) ||
13975 isa<ConstantSDNode>(U->getOperand(1)))
13979 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13980 U->getOperand(1).getOpcode() ==
ISD::SHL)
13990 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13995 auto *C1ShlC2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
13996 auto *C2 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
13997 if (!C1ShlC2 || !C2)
14000 APInt C2Int = C2->getAPIntValue();
14001 APInt C1Int = C1ShlC2->getAPIntValue();
14003 if (C2Int.
uge(C2Width))
14009 if ((C1Int & Mask) != C1Int)
14016 auto LargeImm = [](
const APInt &Imm) {
14017 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
14018 return Imm.getBitWidth() - Zeros > 8;
14021 if (LargeImm(C1Int) || LargeImm(C2Int))
14033 SHL.dump();
N->dump());
14068 if (CSINC.getOpcode() !=
ARMISD::CSINC || !CSINC.hasOneUse())
14077 CSINC.getOperand(0)),
14078 CSINC.getOperand(1), CSINC.getOperand(2),
14079 CSINC.getOperand(3));
14098 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14140 if (!Subtarget->hasVMLxForwarding())
14159 EVT VT =
N->getValueType(0);
14170 EVT VT =
N->getValueType(0);
14171 if (VT != MVT::v2i64)
14180 EVT VT = cast<VTSDNode>(
Op->getOperand(1))->getVT();
14182 return Op->getOperand(0);
14196 And =
And->getOperand(0);
14201 Mask = Mask->getOperand(0);
14204 Mask.getValueType() != MVT::v4i32)
14210 return And->getOperand(0);
14215 if (
SDValue Op0 = IsSignExt(N0)) {
14216 if (
SDValue Op1 = IsSignExt(N1)) {
14222 if (
SDValue Op0 = IsZeroExt(N0)) {
14223 if (
SDValue Op1 = IsZeroExt(N1)) {
14238 EVT VT =
N->getValueType(0);
14239 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14250 if (VT != MVT::i32)
14257 int64_t MulAmt =
C->getSExtValue();
14258 unsigned ShiftAmt = llvm::countr_zero<uint64_t>(MulAmt);
14260 ShiftAmt = ShiftAmt & (32 - 1);
14265 MulAmt >>= ShiftAmt;
14268 if (llvm::has_single_bit<uint32_t>(MulAmt - 1)) {
14276 }
else if (llvm::has_single_bit<uint32_t>(MulAmt + 1)) {
14288 if (llvm::has_single_bit<uint32_t>(MulAmtAbs + 1)) {
14296 }
else if (llvm::has_single_bit<uint32_t>(MulAmtAbs - 1)) {
14326 if (
N->getValueType(0) != MVT::i32)
14335 if (C1 == 255 || C1 == 65535)
14338 SDNode *N0 =
N->getOperand(0).getNode();
14352 if (!C2 || C2 >= 32)
14396 if (Trailing == C2 && C2 + C3 < 32) {
14409 if (Leading == C2 && C2 + C3 < 32) {
14437 EVT VT =
N->getValueType(0);
14441 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14444 APInt SplatBits, SplatUndef;
14445 unsigned SplatBitSize;
14447 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14448 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14449 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14450 SplatBitSize == 64) {
14484 if (!Subtarget->hasV6Ops() ||
14485 (Subtarget->isThumb() &&
14486 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14489 SDValue SRL = OR->getOperand(0);
14490 SDValue SHL = OR->getOperand(1);
14493 SRL = OR->getOperand(1);
14494 SHL = OR->getOperand(0);
14501 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14505 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14506 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14507 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14526 unsigned Opcode = 0;
14527 if (
isS16(OpS16, DAG))
14545 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14548 EVT VT =
N->getValueType(0);
14563 if (VT != MVT::i32)
14576 if (Mask == 0xffff)
14583 if ((Val & ~Mask) != Val)
14608 (Mask == ~Mask2)) {
14611 if (Subtarget->hasDSP() &&
14612 (Mask == 0xffff || Mask == 0xffff0000))
14625 (~Mask == Mask2)) {
14628 if (Subtarget->hasDSP() &&
14629 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14695 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14702 EVT VT =
N->getValueType(0);
14707 auto IsFreelyInvertable = [&](
SDValue V) {
14714 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14730 EVT VT =
N->getValueType(0);
14736 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14737 VT == MVT::v8i1 || VT == MVT::v16i1))
14740 APInt SplatBits, SplatUndef;
14741 unsigned SplatBitSize;
14743 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14744 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14745 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14746 SplatBitSize == 64) {
14782 unsigned SplatBitSize;
14785 APInt SplatBits0, SplatBits1;
14789 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14790 HasAnyUndefs) && !HasAnyUndefs) {
14791 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14792 HasAnyUndefs) && !HasAnyUndefs) {
14797 SplatBits0 == ~SplatBits1) {
14827 EVT VT =
N->getValueType(0);
14842 if (Subtarget->hasMVEIntegerOps()) {
14873 ToMask = ~N->getConstantOperandAPInt(2);
14879 isa<ConstantSDNode>(
From->getOperand(1))) {
14880 APInt Shift =
From->getConstantOperandAPInt(1);
14893 unsigned LastActiveBitInA =
A.countr_zero();
14894 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14895 return LastActiveBitInA - 1 == FirstActiveBitInB;
14900 APInt ToMask, FromMask;
14908 APInt NewToMask, NewFromMask;
14910 if (NewFrom !=
From)
14914 if ((NewToMask & ToMask).getBoolValue())
14939 unsigned InvMask =
N->getConstantOperandVal(2);
14941 unsigned Width = llvm::bit_width<unsigned>(~InvMask) - LSB;
14943 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14944 "undefined behavior");
14945 unsigned Mask = (1u << Width) - 1;
14947 if ((Mask & (~Mask2)) == 0)
14949 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14956 APInt ToMask1, FromMask1;
14959 APInt ToMask2, FromMask2;
14965 APInt NewFromMask = FromMask1 | FromMask2;
14966 APInt NewToMask = ToMask1 | ToMask2;
14968 EVT VT =
N->getValueType(0);
14971 if (NewFromMask[0] == 0)
14983 APInt ToMask1 = ~N->getConstantOperandAPInt(2);
14984 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14986 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14990 EVT VT =
N->getValueType(0);
14993 N->getOperand(1),
N->getOperand(2));
15007 SDValue CSInc = Cmp->getOperand(0);
15057 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15058 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15061 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15063 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15076 SDValue InDouble =
N->getOperand(0);
15085 !cast<LoadSDNode>(InNode)->isVolatile()) {
15091 SDValue BasePtr = LD->getBasePtr();
15093 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15094 LD->getAlign(), LD->getMemOperand()->getFlags());
15100 LD->getPointerInfo().getWithOffset(4),
15102 LD->getMemOperand()->getFlags());
15114 isa<ConstantSDNode>(InDouble.
getOperand(1))) {
15135 if (!Subtarget->
isLittle() && BVSwap)
15145 if (isa<ConstantSDNode>(BV.
getOperand(2))) {
15153 if (!Subtarget->
isLittle() && BVSwap)
15198 if (Copy.getValueType() == MVT::f32 &&
15200 bool HasGlue = Copy->getNumOperands() == 3;
15201 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15202 HasGlue ? Copy->getOperand(2) :
SDValue()};
15203 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15221 if (
LoadSDNode *LN0 = dyn_cast<LoadSDNode>(Op0)) {
15222 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15223 LN0->getMemoryVT() == MVT::i16) {
15226 LN0->getBasePtr(), LN0->getMemOperand());
15244 EVT VT =
N->getValueType(0);
15278 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15279 for (
unsigned i = 0; i < NumElts; ++i) {
15280 SDNode *Elt =
N->getOperand(i).getNode();
15297 if (
N->getNumOperands() == 2)
15303 EVT VT =
N->getValueType(0);
15309 for (
unsigned i = 0; i < NumElts; ++i) {
15335 EVT VT =
N->getValueType(0);
15343 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15348 Use->getValueType(0).isFloatingPoint())
15356 unsigned NumOfBitCastedElts = 0;
15358 unsigned NumOfRelevantElts = NumElts;
15359 for (
unsigned Idx = 0;
Idx < NumElts; ++
Idx) {
15364 ++NumOfBitCastedElts;
15365 }
else if (Elt.
isUndef() || isa<ConstantSDNode>(Elt))
15368 --NumOfRelevantElts;
15372 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15390 for (
unsigned Idx = 0 ;
Idx < NumElts; ++
Idx) {
15395 V->getOperand(0).getValueType() == MVT::i32)
15397 V = V.getOperand(0);
15414 EVT VT =
N->getValueType(0);
15421 if (
Op->getOperand(0).getValueType() == VT)
15422 return Op->getOperand(0);
15437 if (
Op.getValueType() == MVT::i32) {
15448 EVT VT =
N->getValueType(0);
15453 if (ST->isLittle())
15457 if (
Op.getValueType() == VT)
15466 if (
Op->getOperand(0).getValueType() == VT)
15467 return Op->getOperand(0);
15476 if (!Subtarget->hasMVEIntegerOps())
15479 EVT VT =
N->getValueType(0);
15510 EVT VT =
N->getValueType(0);
15511 SDNode *Elt =
N->getOperand(1).getNode();
15526 Vec, V,
N->getOperand(2));
15536 EVT VT =
N->getValueType(0);
15545 Ext.getOperand(0).getValueType() == MVT::f32)
15546 Ext = Ext.getOperand(0);
15548 !isa<ConstantSDNode>(Ext.getOperand(1)) ||
15549 Ext.getConstantOperandVal(1) % 2 != 0)
15551 if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() ==
ISD::SINT_TO_FP ||
15555 SDValue Op0 = Ext.getOperand(0);
15558 unsigned Lane = Ext.getConstantOperandVal(1);
15564 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15565 isa<ConstantSDNode>(V->getOperand(1)) &&
15566 V->getConstantOperandVal(1) == Lane + 1 &&
15567 V->getOperand(0).getResNo() == ResNo;
15569 if (OtherIt == Op0->
users().end())
15574 SDValue OtherExt(*OtherIt, 0);
15587 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15599 EVT VT =
N->getValueType(0);
15605 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15607 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15609 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15612 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15613 X =
X->getOperand(0);
15614 if (
X.getValueType() == VT)
15620 isa<ConstantSDNode>(
N->getOperand(1)) &&
15622 return Op0.
getOperand(
N->getConstantOperandVal(1));
15627 isa<ConstantSDNode>(
N->getOperand(1)) &&
15632 unsigned Offset =
N->getConstantOperandVal(1);
15644 unsigned Idx =
N->getConstantOperandVal(1);
15658 EVT VT =
N->getValueType(0);
15662 cast<VTSDNode>(
N->getOperand(1))->getVT() ==
15663 Op.getOperand(0).getValueType().getScalarType())
15673 SDValue SubVec =
N->getOperand(1);
15674 uint64_t IdxVal =
N->getConstantOperandVal(2);
15685 if (IdxVal == 0 && Vec.
isUndef())
15691 (IdxVal != 0 && IdxVal != NumSubElts))
15764 EVT VT =
N->getValueType(0);
15775 unsigned HalfElts = NumElts/2;
15777 for (
unsigned n = 0; n < NumElts; ++n) {
15780 if (MaskElt < (
int)HalfElts)
15782 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15783 NewElt = HalfElts + MaskElt - NumElts;
15826 bool SimpleConstIncOnly,
15834 bool isLoadOp =
true;
15835 bool isLaneOp =
false;
15838 bool hasAlignment =
true;
15839 unsigned NewOpc = 0;
15840 unsigned NumVecs = 0;
15841 if (
Target.isIntrinsic) {
15842 unsigned IntNo =
N->getConstantOperandVal(1);
15846 case Intrinsic::arm_neon_vld1:
15850 case Intrinsic::arm_neon_vld2:
15854 case Intrinsic::arm_neon_vld3:
15858 case Intrinsic::arm_neon_vld4:
15862 case Intrinsic::arm_neon_vld1x2:
15865 hasAlignment =
false;
15867 case Intrinsic::arm_neon_vld1x3:
15870 hasAlignment =
false;
15872 case Intrinsic::arm_neon_vld1x4:
15875 hasAlignment =
false;
15877 case Intrinsic::arm_neon_vld2dup:
15881 case Intrinsic::arm_neon_vld3dup:
15885 case Intrinsic::arm_neon_vld4dup:
15889 case Intrinsic::arm_neon_vld2lane:
15894 case Intrinsic::arm_neon_vld3lane:
15899 case Intrinsic::arm_neon_vld4lane:
15904 case Intrinsic::arm_neon_vst1:
15909 case Intrinsic::arm_neon_vst2:
15914 case Intrinsic::arm_neon_vst3:
15919 case Intrinsic::arm_neon_vst4:
15924 case Intrinsic::arm_neon_vst2lane:
15930 case Intrinsic::arm_neon_vst3lane:
15936 case Intrinsic::arm_neon_vst4lane:
15942 case Intrinsic::arm_neon_vst1x2:
15946 hasAlignment =
false;
15948 case Intrinsic::arm_neon_vst1x3:
15952 hasAlignment =
false;
15954 case Intrinsic::arm_neon_vst1x4:
15958 hasAlignment =
false;
15963 switch (
N->getOpcode()) {
15999 VecTy =
N->getValueType(0);
16000 }
else if (
Target.isIntrinsic) {
16001 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16004 "Node has to be a load, a store, or an intrinsic!");
16005 VecTy =
N->getOperand(1).getValueType();
16013 if (isLaneOp || isVLDDUPOp)
16016 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16022 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16031 EVT AlignedVecTy = VecTy;
16048 if (isa<LSBaseSDNode>(
N)) {
16051 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16052 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16063 Alignment =
Align(1);
16069 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16071 for (n = 0; n < NumResultVecs; ++n)
16072 Tys[n] = AlignedVecTy;
16073 Tys[n++] = MVT::i32;
16074 Tys[n] = MVT::Other;
16089 unsigned LastOperand =
16090 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16091 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16100 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16111 for (
unsigned i = 0; i < NumResultVecs; ++i)
16116 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16117 SDValue &LdVal = NewResults[0];
16153 switch (
N->getOpcode()) {
16156 if (isa<ConstantSDNode>(
N->getOperand(1))) {
16157 *
Ptr =
N->getOperand(0);
16158 *CInc =
N->getOperand(1);
16164 if (isa<ConstantSDNode>(
N->getOperand(2))) {
16165 *
Ptr =
N->getOperand(1);
16166 *CInc =
N->getOperand(2);
16204 unsigned ConstInc =
16209 if (BaseUpdates.
size() >= MaxBaseUpdates)
16229 unsigned UserOffset =
16232 if (!UserOffset || UserOffset <=
Offset)
16235 unsigned NewConstInc = UserOffset -
Offset;
16238 if (BaseUpdates.
size() >= MaxBaseUpdates)
16245 unsigned NumValidUpd = BaseUpdates.
size();
16246 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16257 return LHS.ConstInc <
RHS.ConstInc;
16286 unsigned IntNo =
N->getConstantOperandVal(1);
16287 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16289 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16312 bool isLoadOp =
true;
16313 unsigned NewOpc = 0;
16314 unsigned NumVecs = 0;
16318 case Intrinsic::arm_mve_vld2q:
16322 case Intrinsic::arm_mve_vld4q:
16326 case Intrinsic::arm_mve_vst2q:
16331 case Intrinsic::arm_mve_vst4q:
16341 VecTy =
N->getValueType(0);
16343 VecTy =
N->getOperand(3).getValueType();
16357 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16359 for (n = 0; n < NumResultVecs; ++n)
16361 Tys[n++] = MVT::i32;
16362 Tys[n] = MVT::Other;
16371 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16379 for (
unsigned i = 0; i < NumResultVecs; ++i)
16398 EVT VT =
N->getValueType(0);
16404 SDNode *VLD =
N->getOperand(0).getNode();
16407 unsigned NumVecs = 0;
16408 unsigned NewOpc = 0;
16410 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16413 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16416 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16428 if (
Use.getResNo() == NumVecs)
16432 VLDLaneNo !=
User->getConstantOperandVal(1))
16439 for (n = 0; n < NumVecs; ++n)
16441 Tys[n] = MVT::Other;
16451 unsigned ResNo =
Use.getResNo();
16453 if (ResNo == NumVecs)
16460 std::vector<SDValue> VLDDupResults;
16461 for (
unsigned n = 0; n < NumVecs; ++n)
16475 EVT VT =
N->getValueType(0);
16478 if (Subtarget->hasMVEIntegerOps()) {
16482 ExtractVT = MVT::i32;
16484 N->getOperand(0),
N->getOperand(1));
16496 Op =
Op.getOperand(0);
16501 unsigned EltSize =
Op.getScalarValueSizeInBits();
16503 unsigned Imm =
Op.getConstantOperandVal(0);
16519 if (Subtarget->hasMVEIntegerOps()) {
16522 if (
Op.getValueType() == MVT::f32)
16525 else if (
Op.getValueType() == MVT::f16)
16530 if (!Subtarget->hasNEON())
16537 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16538 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16539 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16544 LD->getMemoryVT(), LD->getMemOperand());
16555 EVT VT =
N->getValueType(0);
16577 assert(StVT != VT &&
"Cannot truncate to the same type");
16587 if (0 != (NumElems * FromEltSz) % ToEltSz)
16590 unsigned SizeRatio = FromEltSz / ToEltSz;
16595 NumElems * SizeRatio);
16601 for (
unsigned i = 0; i < NumElems; ++i)
16615 MVT StoreType = MVT::i8;
16617 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16636 unsigned E = (ToEltSz * NumElems) / StoreType.
getSizeInBits();
16637 for (
unsigned I = 0;
I < E;
I++) {
16668 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16671 unsigned NumElements = 4;
16688 unsigned Off0 = Rev ? NumElts : 0;
16689 unsigned Off1 = Rev ? 0 : NumElts;
16691 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16692 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16694 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16701 if (
auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Trunc.
getOperand(0)))
16702 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16722 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16737 NewToVT, Alignment, MMOFlags, AAInfo);
16770 unsigned NewOffset =
16778 NewToVT, Alignment, MMOFlags, AAInfo);
16800 {Extract.getOperand(0), Extract.getOperand(1)});
16831 if (Subtarget->hasNEON())
16835 if (Subtarget->hasMVEFloatOps())
16839 if (Subtarget->hasMVEIntegerOps()) {
16914 if (!Subtarget->hasNEON())
16918 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16923 if (!isa<BuildVectorSDNode>(ConstVec))
16926 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16928 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16930 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16931 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16942 if (
C == -1 ||
C == 0 ||
C > 32)
16947 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16948 Intrinsic::arm_neon_vcvtfp2fxu;
16951 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16954 if (IntBits < FloatBits)
16962 if (!Subtarget->hasMVEFloatOps())
16970 EVT VT =
N->getValueType(0);
16975 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16979 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16980 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16982 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16995 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17006 EVT VT =
N->getValueType(0);
17009 if (!
N->getFlags().hasAllowReassociation())
17016 unsigned Opc =
A.getConstantOperandVal(0);
17017 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17022 A.getOperand(3),
A.getOperand(4));
17054 if (!Subtarget->hasNEON())
17058 unsigned OpOpcode =
Op.getNode()->getOpcode();
17059 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17063 SDValue ConstVec =
N->getOperand(1);
17064 if (!isa<BuildVectorSDNode>(ConstVec))
17067 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17069 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17071 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17072 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17092 int32_t
C = IntVal.exactLogBase2();
17093 if (
C == -1 ||
C == 0 ||
C > 32)
17099 if (IntBits < FloatBits)
17101 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17103 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17104 : Intrinsic::arm_neon_vcvtfxu2fp;
17112 if (!ST->hasMVEIntegerOps())
17116 EVT ResVT =
N->getValueType(0);
17144 EVT AVT =
A.getValueType();
17150 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17151 EVT AVT =
A.getValueType();
17163 if (ExtTypeMatches(
A, ExtTypes))
17164 return ExtendIfNeeded(
A, ExtendCode);
17167 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17174 if (Ext->getOpcode() != ExtendCode)
17177 if (ExtTypeMatches(
A, ExtTypes))
17178 return ExtendIfNeeded(
A, ExtendCode);
17191 if (ResVT !=
RetTy)
17194 if (
Mul->getOpcode() == ExtendCode &&
17195 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17197 Mul =
Mul->getOperand(0);
17206 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17207 A = ExtendIfNeeded(
A, ExtendCode);
17208 B = ExtendIfNeeded(
B, ExtendCode);
17226 if (
Mul->getOpcode() == ExtendCode &&
17227 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17229 Mul =
Mul->getOperand(0);
17238 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17239 A = ExtendIfNeeded(
A, ExtendCode);
17240 B = ExtendIfNeeded(
B, ExtendCode);
17251 EVT VT = Ops[0].getValueType();
17252 if (VT == MVT::v16i8) {
17254 "Unexpected illegal long reduction opcode");
17259 DAG.
getVTList(MVT::v8i16, MVT::v8i16), Ops[0]);
17262 DAG.
getVTList(MVT::v8i16, MVT::v8i16), Ops[1]);
17283 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17286 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17350 Op =
Op->getOperand(1);
17352 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17354 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17371 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17372 auto *Shuf = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(VecOp));
17373 if (!Shuf || !Shuf->getOperand(1).isUndef())
17378 APInt SetElts(Mask.size(), 0);
17379 for (
int E : Mask) {
17380 if (E < 0 || E >= (
int)Mask.size())
17387 if (
N->getNumOperands() != VecOp + 1) {
17388 auto *Shuf2 = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(VecOp + 1));
17389 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17395 if (
Op.getValueType().isVector())
17407 unsigned IsTop =
N->getConstantOperandVal(2);
17414 if (Op0->
isUndef() && !IsTop)
17428 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17430 APInt Op0DemandedElts =
17431 IsTop ? Op1DemandedElts
17446 unsigned IsTop =
N->getConstantOperandVal(2);
17448 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17449 APInt Op0DemandedElts =
17461 EVT VT =
N->getValueType(0);
17465 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(
LHS);
17466 auto *Shuf1 = dyn_cast<ShuffleVectorSDNode>(
RHS);
17468 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17469 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17473 LHS.getOperand(0),
RHS.getOperand(0));
17487 if (
auto C = dyn_cast<ConstantSDNode>(
N->getOperand(2))) {
17488 int ShiftAmt =
C->getSExtValue();
17489 if (ShiftAmt == 0) {
17495 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17496 unsigned NewOpcode =
17512 unsigned IntNo =
N->getConstantOperandVal(0);
17523 case Intrinsic::arm_neon_vshifts:
17524 case Intrinsic::arm_neon_vshiftu:
17525 case Intrinsic::arm_neon_vrshifts:
17526 case Intrinsic::arm_neon_vrshiftu:
17527 case Intrinsic::arm_neon_vrshiftn:
17528 case Intrinsic::arm_neon_vqshifts:
17529 case Intrinsic::arm_neon_vqshiftu:
17530 case Intrinsic::arm_neon_vqshiftsu:
17531 case Intrinsic::arm_neon_vqshiftns:
17532 case Intrinsic::arm_neon_vqshiftnu:
17533 case Intrinsic::arm_neon_vqshiftnsu:
17534 case Intrinsic::arm_neon_vqrshiftns:
17535 case Intrinsic::arm_neon_vqrshiftnu:
17536 case Intrinsic::arm_neon_vqrshiftnsu: {
17537 EVT VT =
N->getOperand(1).getValueType();
17539 unsigned VShiftOpc = 0;
17542 case Intrinsic::arm_neon_vshifts:
17543 case Intrinsic::arm_neon_vshiftu:
17548 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17555 case Intrinsic::arm_neon_vrshifts:
17556 case Intrinsic::arm_neon_vrshiftu:
17561 case Intrinsic::arm_neon_vqshifts:
17562 case Intrinsic::arm_neon_vqshiftu:
17567 case Intrinsic::arm_neon_vqshiftsu:
17572 case Intrinsic::arm_neon_vrshiftn:
17573 case Intrinsic::arm_neon_vqshiftns:
17574 case Intrinsic::arm_neon_vqshiftnu:
17575 case Intrinsic::arm_neon_vqshiftnsu:
17576 case Intrinsic::arm_neon_vqrshiftns:
17577 case Intrinsic::arm_neon_vqrshiftnu:
17578 case Intrinsic::arm_neon_vqrshiftnsu:
17590 case Intrinsic::arm_neon_vshifts:
17591 case Intrinsic::arm_neon_vshiftu:
17594 case Intrinsic::arm_neon_vrshifts:
17597 case Intrinsic::arm_neon_vrshiftu:
17600 case Intrinsic::arm_neon_vrshiftn:
17603 case Intrinsic::arm_neon_vqshifts:
17606 case Intrinsic::arm_neon_vqshiftu:
17609 case Intrinsic::arm_neon_vqshiftsu:
17612 case Intrinsic::arm_neon_vqshiftns:
17615 case Intrinsic::arm_neon_vqshiftnu:
17618 case Intrinsic::arm_neon_vqshiftnsu:
17621 case Intrinsic::arm_neon_vqrshiftns:
17624 case Intrinsic::arm_neon_vqrshiftnu:
17627 case Intrinsic::arm_neon_vqrshiftnsu:
17633 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17634 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17637 case Intrinsic::arm_neon_vshiftins: {
17638 EVT VT =
N->getOperand(1).getValueType();
17640 unsigned VShiftOpc = 0;
17644 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17651 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17652 N->getOperand(1),
N->getOperand(2),
17656 case Intrinsic::arm_neon_vqrshifts:
17657 case Intrinsic::arm_neon_vqrshiftu:
17661 case Intrinsic::arm_neon_vbsl: {
17664 N->getOperand(2),
N->getOperand(3));
17666 case Intrinsic::arm_mve_vqdmlah:
17667 case Intrinsic::arm_mve_vqdmlash:
17668 case Intrinsic::arm_mve_vqrdmlah:
17669 case Intrinsic::arm_mve_vqrdmlash:
17670 case Intrinsic::arm_mve_vmla_n_predicated:
17671 case Intrinsic::arm_mve_vmlas_n_predicated:
17672 case Intrinsic::arm_mve_vqdmlah_predicated:
17673 case Intrinsic::arm_mve_vqdmlash_predicated:
17674 case Intrinsic::arm_mve_vqrdmlah_predicated:
17675 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17680 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17687 case Intrinsic::arm_mve_minv:
17688 case Intrinsic::arm_mve_maxv:
17689 case Intrinsic::arm_mve_minav:
17690 case Intrinsic::arm_mve_maxav:
17691 case Intrinsic::arm_mve_minv_predicated:
17692 case Intrinsic::arm_mve_maxv_predicated:
17693 case Intrinsic::arm_mve_minav_predicated:
17694 case Intrinsic::arm_mve_maxav_predicated: {
17697 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17704 case Intrinsic::arm_mve_addv: {
17707 bool Unsigned =
N->getConstantOperandVal(2);
17712 case Intrinsic::arm_mve_addlv:
17713 case Intrinsic::arm_mve_addlv_predicated: {
17716 bool Unsigned =
N->getConstantOperandVal(2);
17717 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17722 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17745 EVT VT =
N->getValueType(0);
17747 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17748 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17749 N->getOperand(0)->hasOneUse()) {
17757 ConstantSDNode *ShiftAmtNode = dyn_cast<ConstantSDNode>(
N->getOperand(1));
17766 if (AndMask == 255 || AndMask == 65535)
17770 if (MaskedBits > ShiftAmt) {
17785 if (ST->hasMVEIntegerOps())
17790 switch (
N->getOpcode()) {
17803 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17804 unsigned VShiftOpc =
17807 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17823 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17826 EVT FromVT = LD->getValueType(0);
17827 EVT ToVT =
N->getValueType(0);
17834 unsigned NumElements = 0;
17835 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17837 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17839 if (NumElements == 0 ||
17849 SDValue BasePtr = LD->getBasePtr();
17850 Align Alignment = LD->getBaseAlign();
17871 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17872 Alignment, MMOFlags, AAInfo);
17878 if (FromEltVT == MVT::f16) {
17881 for (
unsigned i = 0; i < Loads.
size(); i++) {
17907 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17911 EVT VT =
N->getValueType(0);
17915 if (VT == MVT::i32 &&
17916 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17918 isa<ConstantSDNode>(Lane)) {
17921 switch (
N->getOpcode()) {
17935 if (ST->hasMVEIntegerOps())
17944 if (ST->hasMVEFloatOps())
17955 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17959 EVT VT =
Op.getValueType();
17962 if (VT != MVT::i32 ||
17964 !isa<ConstantSDNode>(
Op.getOperand(1)) ||
17975 APInt MaxC = Max.getConstantOperandAPInt(1);
17978 !(MinC + 1).isPowerOf2())
17996 EVT VT =
N->getValueType(0);
17999 if (VT == MVT::i32)
18002 if (!ST->hasMVEIntegerOps())
18008 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18011 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18019 if (VT == MVT::v4i32)
18020 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18022 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18029 MaxC != ~SaturateC)
18034 if (IsSignedSaturate(
N, N0.
getNode())) {
18037 if (VT == MVT::v4i32) {
18038 HalfVT = MVT::v8i16;
18039 ExtVT = MVT::v4i16;
18041 HalfVT = MVT::v16i8;
18056 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18062 if (VT == MVT::v4i32)
18063 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18065 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18074 if (IsUnsignedSaturate(
N)) {
18078 if (VT == MVT::v4i32) {
18079 HalfVT = MVT::v8i16;
18080 ExtConst = 0x0000FFFF;
18082 HalfVT = MVT::v16i8;
18104 const APInt *CV = &
C->getAPIntValue();
18122 SDValue Op0 = CMOV->getOperand(0);
18123 SDValue Op1 = CMOV->getOperand(1);
18124 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
18125 SDValue CmpZ = CMOV->getOperand(3);
18161 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18168 if ((OrCI & Known.
Zero) != OrCI)
18174 EVT VT =
X.getValueType();
18175 unsigned BitInX = AndC->
logBase2();
18183 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18184 BitInY < NumActiveBits; ++BitInY) {
18185 if (OrCI[BitInY] == 0)
18188 Mask.setBit(BitInY);
18205 switch (
N->getOpcode()) {
18209 if (!isa<ConstantSDNode>(
N.getOperand(1)))
18211 if (!cast<ConstantSDNode>(
N.getOperand(1))->isOne())
18217 auto *Const = dyn_cast<ConstantSDNode>(
N.getOperand(1));
18220 if (Const->isZero())
18222 else if (Const->isOne())
18226 CC = cast<CondCodeSDNode>(
N.getOperand(2))->get();
18230 unsigned IntOp =
N.getConstantOperandVal(1);
18231 if (IntOp != Intrinsic::test_start_loop_iterations &&
18232 IntOp != Intrinsic::loop_decrement_reg)
18258 bool Negate =
false;
18264 Cond =
N->getOperand(1);
18265 Dest =
N->getOperand(2);
18268 CC = cast<CondCodeSDNode>(
N->getOperand(1))->get();
18269 Cond =
N->getOperand(2);
18270 Dest =
N->getOperand(4);
18271 if (
auto *Const = dyn_cast<ConstantSDNode>(
N->getOperand(3))) {
18272 if (!Const->isOne() && !Const->isZero())
18274 Imm = Const->getZExtValue();
18302 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18303 "unsupported condition");
18308 unsigned IntOp =
Int->getConstantOperandVal(1);
18309 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18310 "expected single br user");
18311 SDNode *Br = *
N->user_begin();
18321 if (IntOp == Intrinsic::test_start_loop_iterations) {
18325 if (IsTrueIfZero(CC, Imm)) {
18326 SDValue Ops[] = {Chain, Setup, Dest};
18331 UpdateUncondBr(Br, Dest, DAG);
18333 SDValue Ops[] = {Chain, Setup, OtherTarget};
18346 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18350 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18354 if (
Target == OtherTarget)
18355 UpdateUncondBr(Br, Dest, DAG);
18391 LHS->getOperand(0)->getOperand(2),
18392 LHS->getOperand(0)->getOperand(3));
18406 EVT VT =
N->getValueType(0);
18410 SDValue FalseVal =
N->getOperand(0);
18411 SDValue TrueVal =
N->getOperand(1);
18416 if (!Subtarget->
isThumb1Only() && Subtarget->hasV6T2Ops()) {
18454 LHS->getOperand(2),
LHS->getOperand(3));
18464 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18468 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18470 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18479 if (!Subtarget->
isThumb1Only() && Subtarget->hasV5TOps()) {
18544 const APInt *TrueConst;
18546 ((FalseVal.getOpcode() ==
ARMISD::SUBC && FalseVal.getOperand(0) ==
LHS &&
18547 FalseVal.getOperand(1) ==
RHS) ||
18551 unsigned ShiftAmount = TrueConst->
logBase2();
18566 if (Known.
Zero == 0xfffffffe)
18569 else if (Known.
Zero == 0xffffff00)
18572 else if (Known.
Zero == 0xffff0000)
18585 EVT DstVT =
N->getValueType(0);
18588 if (ST->hasMVEIntegerOps() && Src.getOpcode() ==
ARMISD::VDUP) {
18589 EVT SrcVT = Src.getValueType();
18597 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18598 Src.getValueType().getScalarSizeInBits())
18599 Src = Src.getOperand(0);
18603 EVT SrcVT = Src.getValueType();
18623 EVT VT =
N->getValueType(0);
18631 if (
N->getNumOperands() == 2 &&
18635 N->getOperand(0).getOperand(1),
18636 N->getOperand(1).getOperand(0),
18637 N->getOperand(1).getOperand(1));
18640 if (
N->getNumOperands() == 2 &&
18643 auto *S0 = cast<ShuffleVectorSDNode>(
N->getOperand(0).getNode());
18644 auto *
S1 = cast<ShuffleVectorSDNode>(
N->getOperand(1).getNode());
18646 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18647 S0->getOperand(1) ==
S1->getOperand(1)) {
18650 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18670 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18671 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18672 (Op.getOpcode() == ISD::BITCAST &&
18673 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18676 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18678 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18695 int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
18696 int NumIns =
N->getNumOperands();
18697 assert((NumIns == 2 || NumIns == 4) &&
18698 "Expected 2 or 4 inputs to an MVETrunc");
18700 if (
N->getNumOperands() == 4)
18704 for (
int I = 0;
I < NumIns;
I++) {
18706 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18726 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18729 EVT FromVT = LD->getMemoryVT();
18730 EVT ToVT =
N->getValueType(0);
18737 unsigned NumElements = 0;
18738 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18740 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18742 assert(NumElements != 0);
18748 LD->getExtensionType() != NewExtType)
18755 SDValue BasePtr = LD->getBasePtr();
18756 Align Alignment = LD->getBaseAlign();
18775 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18776 Alignment, MMOFlags, AAInfo);
18792 EVT VT =
N->getValueType(0);
18794 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18795 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18797 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18799 auto Extend = [&](
SDValue V) {
18809 SDValue Ext = Extend(
N->getOperand(0));
18814 if (
auto *SVN = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(0))) {
18817 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18822 auto CheckInregMask = [&](
int Start,
int Offset) {
18830 if (CheckInregMask(0, 0))
18832 else if (CheckInregMask(0, 1))
18833 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18834 else if (CheckInregMask(0, Mask.size()))
18836 else if (CheckInregMask(0, Mask.size() + 1))
18837 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18842 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18846 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18853 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
18863 int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
18864 int NumOuts =
N->getNumValues();
18865 assert((NumOuts == 2 || NumOuts == 4) &&
18866 "Expected 2 or 4 outputs to an MVEEXT");
18867 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18869 if (
N->getNumOperands() == 4)
18875 StackPtr, MPI,
Align(4));
18878 for (
int I = 0;
I < NumOuts;
I++) {
18880 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18881 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18886 VT, Chain,
Ptr, MPI, LoadVT,
Align(4));
18895 switch (
N->getOpcode()) {
19012 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19019 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19030 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19038 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19040 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19048 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19050 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19058 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19069 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19077 if (
N->getOperand(1) ==
N->getOperand(2))
19078 return N->getOperand(1);
19082 switch (
N->getConstantOperandVal(1)) {
19083 case Intrinsic::arm_neon_vld1:
19084 case Intrinsic::arm_neon_vld1x2:
19085 case Intrinsic::arm_neon_vld1x3:
19086 case Intrinsic::arm_neon_vld1x4:
19087 case Intrinsic::arm_neon_vld2:
19088 case Intrinsic::arm_neon_vld3:
19089 case Intrinsic::arm_neon_vld4:
19090 case Intrinsic::arm_neon_vld2lane:
19091 case Intrinsic::arm_neon_vld3lane:
19092 case Intrinsic::arm_neon_vld4lane:
19093 case Intrinsic::arm_neon_vld2dup:
19094 case Intrinsic::arm_neon_vld3dup:
19095 case Intrinsic::arm_neon_vld4dup:
19096 case Intrinsic::arm_neon_vst1:
19097 case Intrinsic::arm_neon_vst1x2:
19098 case Intrinsic::arm_neon_vst1x3:
19099 case Intrinsic::arm_neon_vst1x4:
19100 case Intrinsic::arm_neon_vst2:
19101 case Intrinsic::arm_neon_vst3:
19102 case Intrinsic::arm_neon_vst4:
19103 case Intrinsic::arm_neon_vst2lane:
19104 case Intrinsic::arm_neon_vst3lane:
19105 case Intrinsic::arm_neon_vst4lane:
19107 case Intrinsic::arm_mve_vld2q:
19108 case Intrinsic::arm_mve_vld4q:
19109 case Intrinsic::arm_mve_vst2q:
19110 case Intrinsic::arm_mve_vst4q:
19127 unsigned *
Fast)
const {
19136 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19138 if (AllowsUnaligned) {
19140 *
Fast = Subtarget->hasV7Ops();
19145 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19149 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->
isLittle())) {
19156 if (!Subtarget->hasMVEIntegerOps())
19160 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19161 Ty == MVT::v2i1)) {
19169 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19185 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19186 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19187 Ty == MVT::v2f64) {
19200 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19201 !FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat)) {
19203 if (
Op.size() >= 16 &&
19209 }
else if (
Op.size() >= 8 &&
19230 return (SrcBits == 64 && DestBits == 32);
19239 return (SrcBits == 64 && DestBits == 32);
19275 return Subtarget->hasFullFP16();
19282 if (!Subtarget->hasMVEIntegerOps())
19300 if (
auto *Ld = dyn_cast<MaskedLoadSDNode>(ExtVal.
getOperand(0))) {
19301 if (Ld->isExpandingLoad())
19305 if (Subtarget->hasMVEIntegerOps())
19350bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19352 if (Subtarget->useSoftFloat())
19361 return Subtarget->hasMVEFloatOps();
19379 unsigned Scale = 1;
19396 if ((V & (Scale - 1)) != 0)
19398 return isUInt<5>(V / Scale);
19405 if (VT.
isVector() && Subtarget->hasNEON())
19408 !Subtarget->hasMVEFloatOps())
19411 bool IsNeg =
false;
19417 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19420 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19424 return isShiftedUInt<7,2>(V);
19427 return isShiftedUInt<7,1>(V);
19429 return isUInt<7>(V);
19436 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19437 return isShiftedUInt<8, 1>(V);
19440 return isShiftedUInt<8, 2>(V);
19442 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19445 return isUInt<8>(V);
19446 return isUInt<12>(V);
19472 default:
return false;
19477 return isUInt<12>(V);
19480 return isUInt<8>(V);
19485 return isShiftedUInt<8, 2>(V);
19491 int Scale = AM.
Scale;
19496 default:
return false;
19504 Scale = Scale & ~1;
19505 return Scale == 2 || Scale == 4 || Scale == 8;
19522 if (Scale & 1)
return false;
19529 const int Scale = AM.
Scale;
19539 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19555 switch (AM.
Scale) {
19572 int Scale = AM.
Scale;
19574 default:
return false;
19578 if (Scale < 0) Scale = -Scale;
19586 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19599 if (Scale & 1)
return false;
19612 if (!Subtarget->isThumb())
19619 return Imm >= 0 && Imm <= 255;
19629 if (!Subtarget->isThumb())
19634 return AbsImm <= 255;
19669 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19673 int RHSC = (int)
RHS->getZExtValue();
19674 if (RHSC < 0 && RHSC > -256) {
19684 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19687 int RHSC = (int)
RHS->getZExtValue();
19688 if (RHSC < 0 && RHSC > -0x1000) {
19730 int RHSC = (int)
RHS->getZExtValue();
19731 if (RHSC < 0 && RHSC > -0x100) {
19736 }
else if (RHSC > 0 && RHSC < 0x100) {
19747 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19752 if (!isa<ConstantSDNode>(
Ptr->getOperand(1)))
19758 bool CanChangeType = isLE && !IsMasked;
19761 int RHSC = (int)
RHS->getZExtValue();
19763 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19764 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19769 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19780 if (VT == MVT::v4i16) {
19781 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19783 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19784 if (IsInRange(RHSC, 0x80, 1))
19786 }
else if (Alignment >= 4 &&
19787 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19788 IsInRange(RHSC, 0x80, 4))
19790 else if (Alignment >= 2 &&
19791 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19792 IsInRange(RHSC, 0x80, 2))
19794 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19813 bool isSEXTLoad =
false;
19814 bool IsMasked =
false;
19816 Ptr = LD->getBasePtr();
19817 VT = LD->getMemoryVT();
19818 Alignment = LD->getAlign();
19820 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
19821 Ptr = ST->getBasePtr();
19822 VT = ST->getMemoryVT();
19823 Alignment = ST->getAlign();
19825 Ptr = LD->getBasePtr();
19826 VT = LD->getMemoryVT();
19827 Alignment = LD->getAlign();
19831 Ptr = ST->getBasePtr();
19832 VT = ST->getMemoryVT();
19833 Alignment = ST->getAlign();
19839 bool isLegal =
false;
19841 isLegal = Subtarget->hasMVEIntegerOps() &&
19843 Ptr.getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19871 bool isSEXTLoad =
false, isNonExt;
19872 bool IsMasked =
false;
19874 VT = LD->getMemoryVT();
19875 Ptr = LD->getBasePtr();
19876 Alignment = LD->getAlign();
19879 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
19880 VT = ST->getMemoryVT();
19881 Ptr = ST->getBasePtr();
19882 Alignment = ST->getAlign();
19883 isNonExt = !ST->isTruncatingStore();
19885 VT = LD->getMemoryVT();
19886 Ptr = LD->getBasePtr();
19887 Alignment = LD->getAlign();
19892 VT = ST->getMemoryVT();
19893 Ptr = ST->getBasePtr();
19894 Alignment = ST->getAlign();
19895 isNonExt = !ST->isTruncatingStore();
19903 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19904 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19906 auto *
RHS = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
19907 if (!
RHS ||
RHS->getZExtValue() != 4)
19909 if (Alignment <
Align(4))
19913 Base =
Op->getOperand(0);
19919 bool isLegal =
false;
19921 isLegal = Subtarget->hasMVEIntegerOps() &&
19954 const APInt &DemandedElts,
19956 unsigned Depth)
const {
19959 switch (
Op.getOpcode()) {
19966 if (
Op.getResNo() == 0) {
19992 case Intrinsic::arm_ldaex:
19993 case Intrinsic::arm_ldrex: {
19994 EVT VT = cast<MemIntrinsicSDNode>(
Op)->getMemoryVT();
20008 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20009 Known.
Zero &= Mask;
20015 const SDValue &SrcSV =
Op.getOperand(0);
20021 "VGETLANE index out of bounds");
20026 EVT VT =
Op.getValueType();
20033 Known = Known.
sext(DstSz);
20035 Known = Known.
zext(DstSz);
20043 Known = KnownOp.
zext(32);
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) &&
20166 isa<ConstantSDNode>(
Op->getOperand(2))) {
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);
20197 if (!Subtarget->hasV6Ops())
20203 SplitString(AsmStr, AsmPieces,
";\n");
20205 switch (AsmPieces.
size()) {
20206 default:
return false;
20208 AsmStr = AsmPieces[0];
20210 SplitString(AsmStr, AsmPieces,
" \t,");
20213 if (AsmPieces.
size() == 3 && AsmPieces[0] ==
"rev" &&
20214 AsmPieces[1] ==
"$0" && AsmPieces[2] ==
"$1" &&
20215 IA->getConstraintString().starts_with(
"=l,l")) {
20238 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20250 unsigned S = Constraint.
size();
20252 switch (Constraint[0]) {
20264 }
else if (S == 2) {
20265 switch (Constraint[0]) {
20282 Value *CallOperandVal =
info.CallOperandVal;
20285 if (!CallOperandVal)
20289 switch (*constraint) {
20295 if (Subtarget->isThumb())
20310 if (PR == 0 || VT == MVT::Other)
20312 return (ARM::SPRRegClass.
contains(PR) && VT != MVT::f32 && VT != MVT::i32) ||
20313 (ARM::DPRRegClass.contains(PR) && VT != MVT::f64 &&
20317using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20321 switch (Constraint.
size()) {
20324 switch (Constraint[0]) {
20326 if (Subtarget->isThumb())
20327 return RCPair(0U, &ARM::tGPRRegClass);
20328 return RCPair(0U, &ARM::GPRRegClass);
20330 if (Subtarget->isThumb())
20331 return RCPair(0U, &ARM::hGPRRegClass);
20335 return RCPair(0U, &ARM::tGPRRegClass);
20336 return RCPair(0U, &ARM::GPRRegClass);
20338 if (VT == MVT::Other)
20340 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20341 return RCPair(0U, &ARM::SPRRegClass);
20343 return RCPair(0U, &ARM::DPRRegClass);
20345 return RCPair(0U, &ARM::QPRRegClass);
20348 if (VT == MVT::Other)
20350 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20351 return RCPair(0U, &ARM::SPR_8RegClass);
20353 return RCPair(0U, &ARM::DPR_8RegClass);
20355 return RCPair(0U, &ARM::QPR_8RegClass);
20358 if (VT == MVT::Other)
20360 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20361 return RCPair(0U, &ARM::SPRRegClass);
20363 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20365 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20371 if (Constraint[0] ==
'T') {
20372 switch (Constraint[1]) {
20376 return RCPair(0U, &ARM::tGPREvenRegClass);
20378 return RCPair(0U, &ARM::tGPROddRegClass);
20387 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20388 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20392 return {0,
nullptr};
20400 std::vector<SDValue> &Ops,
20405 if (Constraint.
size() != 1)
20408 char ConstraintLetter = Constraint[0];
20409 switch (ConstraintLetter) {
20412 case 'I':
case 'J':
case 'K':
case 'L':
20413 case 'M':
case 'N':
case 'O':
20418 int64_t CVal64 =
C->getSExtValue();
20419 int CVal = (int) CVal64;
20422 if (CVal != CVal64)
20425 switch (ConstraintLetter) {
20429 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20430 if (CVal >= 0 && CVal <= 65535)
20437 if (CVal >= 0 && CVal <= 255)
20439 }
else if (Subtarget->
isThumb2()) {
20458 if (CVal >= -255 && CVal <= -1)
20464 if (CVal >= -4095 && CVal <= 4095)
20477 }
else if (Subtarget->
isThumb2()) {
20500 if (CVal >= -7 && CVal < 7)
20502 }
else if (Subtarget->
isThumb2()) {
20525 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20531 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20539 if (CVal >= 0 && CVal <= 31)
20548 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20557 if (Result.getNode()) {
20558 Ops.push_back(Result);
20568 "Unhandled Opcode in getDivRemLibcall");
20574 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20575 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20576 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20577 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20586 "Unhandled Opcode in getDivRemArgList");
20590 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20591 EVT ArgVT =
N->getOperand(i).getValueType();
20596 Args.push_back(Entry);
20607 "Register-based DivRem lowering only");
20608 unsigned Opcode =
Op->getOpcode();
20610 "Invalid opcode for Div/Rem lowering");
20612 EVT VT =
Op->getValueType(0);
20615 if (VT == MVT::i64 && isa<ConstantSDNode>(
Op.getOperand(1))) {
20634 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20635 : Subtarget->hasDivideInARMMode();
20636 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20637 Op->getSimpleValueType(0) == MVT::i32) {
20639 const SDValue Dividend =
Op->getOperand(0);
20640 const SDValue Divisor =
Op->getOperand(1);
20641 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20645 SDValue Values[2] = {Div, Rem};
20677 EVT VT =
N->getValueType(0);
20679 if (VT == MVT::i64 && isa<ConstantSDNode>(
N->getOperand(1))) {
20683 Result[0], Result[1]);
20687 std::vector<Type*> RetTyParams;
20688 Type *RetTyElement;
20698 RetTyParams.push_back(RetTyElement);
20699 RetTyParams.push_back(RetTyElement);
20716 CallLoweringInfo CLI(DAG);
20720 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20723 SDNode *ResNode = CallResult.first.getNode();
20738 "no-stack-arg-probe")) {
20740 cast<ConstantSDNode>(
Op.getOperand(2))->getMaybeAlignValue();
20742 Chain =
SP.getValue(1);
20765 SDValue Ops[2] = { NewSP, Chain };
20770 bool IsStrict =
Op->isStrictFPOpcode();
20771 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20772 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20774 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20775 "Unexpected type for custom-lowering FP_EXTEND");
20778 "With both FP DP and 16, any FP conversion is legal!");
20780 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20781 "With FP16, 16 to 32 conversion is legal!");
20784 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20789 Loc,
Op.getValueType(), SrcVal);
20802 MakeLibCallOptions CallOptions;
20804 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20805 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20806 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20807 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20811 {DstVT, MVT::Other}, {Chain, SrcVal});
20818 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20819 "Unexpected type for custom-lowering FP_EXTEND");
20820 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20825 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20829 bool IsStrict =
Op->isStrictFPOpcode();
20831 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20833 EVT DstVT =
Op.getValueType();
20834 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20837 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20838 "Unexpected type for custom-lowering FP_ROUND");
20841 "With both FP DP and 16, any FP conversion is legal!");
20846 if (SrcSz == 32 && Subtarget->hasFP16())
20851 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20852 "Unexpected type for custom-lowering FP_ROUND");
20853 MakeLibCallOptions CallOptions;
20856 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20868 if (v == 0xffffffff)
20880 bool ForCodeSize)
const {
20883 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20885 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20888 if (VT == MVT::f32)
20890 if (VT == MVT::f64 && Subtarget->hasFP64())
20901 unsigned Intrinsic)
const {
20902 switch (Intrinsic) {
20903 case Intrinsic::arm_neon_vld1:
20904 case Intrinsic::arm_neon_vld2:
20905 case Intrinsic::arm_neon_vld3:
20906 case Intrinsic::arm_neon_vld4:
20907 case Intrinsic::arm_neon_vld2lane:
20908 case Intrinsic::arm_neon_vld3lane:
20909 case Intrinsic::arm_neon_vld4lane:
20910 case Intrinsic::arm_neon_vld2dup:
20911 case Intrinsic::arm_neon_vld3dup:
20912 case Intrinsic::arm_neon_vld4dup: {
20915 auto &
DL =
I.getDataLayout();
20916 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20918 Info.ptrVal =
I.getArgOperand(0);
20920 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20921 Info.align = cast<ConstantInt>(AlignArg)->getMaybeAlignValue();
20926 case Intrinsic::arm_neon_vld1x2:
20927 case Intrinsic::arm_neon_vld1x3:
20928 case Intrinsic::arm_neon_vld1x4: {
20931 auto &
DL =
I.getDataLayout();
20932 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20934 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20936 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20941 case Intrinsic::arm_neon_vst1:
20942 case Intrinsic::arm_neon_vst2:
20943 case Intrinsic::arm_neon_vst3:
20944 case Intrinsic::arm_neon_vst4:
20945 case Intrinsic::arm_neon_vst2lane:
20946 case Intrinsic::arm_neon_vst3lane:
20947 case Intrinsic::arm_neon_vst4lane: {
20950 auto &
DL =
I.getDataLayout();
20951 unsigned NumElts = 0;
20952 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20953 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20956 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20959 Info.ptrVal =
I.getArgOperand(0);
20961 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20962 Info.align = cast<ConstantInt>(AlignArg)->getMaybeAlignValue();
20967 case Intrinsic::arm_neon_vst1x2:
20968 case Intrinsic::arm_neon_vst1x3:
20969 case Intrinsic::arm_neon_vst1x4: {
20972 auto &
DL =
I.getDataLayout();
20973 unsigned NumElts = 0;
20974 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20975 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20978 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20981 Info.ptrVal =
I.getArgOperand(0);
20983 Info.align =
I.getParamAlign(0).valueOrOne();
20988 case Intrinsic::arm_mve_vld2q:
20989 case Intrinsic::arm_mve_vld4q: {
20992 Type *VecTy = cast<StructType>(
I.getType())->getElementType(1);
20993 unsigned Factor = Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
20995 Info.ptrVal =
I.getArgOperand(0);
21002 case Intrinsic::arm_mve_vst2q:
21003 case Intrinsic::arm_mve_vst4q: {
21006 Type *VecTy =
I.getArgOperand(1)->getType();
21007 unsigned Factor = Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21009 Info.ptrVal =
I.getArgOperand(0);
21016 case Intrinsic::arm_mve_vldr_gather_base:
21017 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21019 Info.ptrVal =
nullptr;
21025 case Intrinsic::arm_mve_vldr_gather_base_wb:
21026 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21028 Info.ptrVal =
nullptr;
21034 case Intrinsic::arm_mve_vldr_gather_offset:
21035 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21037 Info.ptrVal =
nullptr;
21039 unsigned MemSize = cast<ConstantInt>(
I.getArgOperand(2))->getZExtValue();
21046 case Intrinsic::arm_mve_vstr_scatter_base:
21047 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21049 Info.ptrVal =
nullptr;
21055 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21056 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21058 Info.ptrVal =
nullptr;
21064 case Intrinsic::arm_mve_vstr_scatter_offset:
21065 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21067 Info.ptrVal =
nullptr;
21069 unsigned MemSize = cast<ConstantInt>(
I.getArgOperand(3))->getZExtValue();
21076 case Intrinsic::arm_ldaex:
21077 case Intrinsic::arm_ldrex: {
21078 auto &
DL =
I.getDataLayout();
21079 Type *ValTy =
I.getParamElementType(0);
21082 Info.ptrVal =
I.getArgOperand(0);
21084 Info.align =
DL.getABITypeAlign(ValTy);
21088 case Intrinsic::arm_stlex:
21089 case Intrinsic::arm_strex: {
21090 auto &
DL =
I.getDataLayout();
21091 Type *ValTy =
I.getParamElementType(1);
21094 Info.ptrVal =
I.getArgOperand(1);
21096 Info.align =
DL.getABITypeAlign(ValTy);
21100 case Intrinsic::arm_stlexd:
21101 case Intrinsic::arm_strexd:
21103 Info.memVT = MVT::i64;
21104 Info.ptrVal =
I.getArgOperand(2);
21110 case Intrinsic::arm_ldaexd:
21111 case Intrinsic::arm_ldrexd:
21113 Info.memVT = MVT::i64;
21114 Info.ptrVal =
I.getArgOperand(0);
21134 if (Bits == 0 || Bits > 32)
21140 unsigned Index)
const {
21150 if (!Subtarget->hasDataBarrier()) {
21154 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21189 if (Subtarget->preferISHSTBarriers())
21222 bool has64BitAtomicStore;
21224 has64BitAtomicStore =
false;
21225 else if (Subtarget->isThumb())
21226 has64BitAtomicStore = Subtarget->hasV7Ops();
21228 has64BitAtomicStore = Subtarget->hasV6Ops();
21230 unsigned Size = SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21244 bool has64BitAtomicLoad;
21246 has64BitAtomicLoad =
false;
21247 else if (Subtarget->isThumb())
21248 has64BitAtomicLoad = Subtarget->hasV7Ops();
21250 has64BitAtomicLoad = Subtarget->hasV6Ops();
21267 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21268 else if (Subtarget->isThumb())
21269 hasAtomicRMW = Subtarget->hasV7Ops();
21271 hasAtomicRMW = Subtarget->hasV6Ops();
21272 if (
Size <= (Subtarget->
isMClass() ? 32U : 64U) && hasAtomicRMW) {
21295 bool HasAtomicCmpXchg;
21297 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21298 else if (Subtarget->isThumb())
21299 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21301 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21303 HasAtomicCmpXchg &&
Size <= (Subtarget->
isMClass() ? 32U : 64U))
21310 return InsertFencesForAtomic;
21319 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21321 if (SecurityCheckCookieLibcall == RTLIB::Unsupported)
21325 M.getOrInsertGlobal(
"__security_cookie",
21333 F->addParamAttr(0, Attribute::AttrKind::InReg);
21338 RTLIB::LibcallImpl SecurityCheckCookie =
21340 if (SecurityCheckCookie != RTLIB::Unsupported)
21346 unsigned &
Cost)
const {
21348 if (!Subtarget->hasNEON())
21360 if (!isa<ConstantInt>(
Idx))
21375 return Subtarget->hasV5TOps() && !Subtarget->
isThumb1Only();
21379 return Subtarget->hasV5TOps() && !Subtarget->
isThumb1Only();
21384 if (!Subtarget->hasV7Ops())
21390 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21392 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21417 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21429 Lo, Builder.
CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21432 Type *Tys[] = {
Addr->getType() };
21433 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21437 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21443 if (!Subtarget->hasV7Ops())
21459 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21469 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21470 Type *Tys[] = {
Addr->getType() };
21492 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21499 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21502 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21510 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21518 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21521 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21526 if (Subtarget->hasNEON() && VecSize == 64)
21528 return VecSize % 128 == 0;
21532 if (Subtarget->hasNEON())
21534 if (Subtarget->hasMVEIntegerOps())
21554 "Invalid interleave factor");
21555 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21557 "Unmatched number of shufflevectors and indices");
21559 auto *LI = dyn_cast<LoadInst>(Load);
21562 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21564 auto *VecTy = cast<FixedVectorType>(Shuffles[0]->
getType());
21565 Type *EltTy = VecTy->getElementType();
21568 Align Alignment = LI->getAlign();
21586 Value *BaseAddr = LI->getPointerOperand();
21588 if (NumLoads > 1) {
21592 VecTy->getNumElements() / NumLoads);
21598 if (Subtarget->hasNEON()) {
21599 Type *PtrTy = Builder.
getPtrTy(LI->getPointerAddressSpace());
21600 Type *Tys[] = {VecTy, PtrTy};
21601 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21602 Intrinsic::arm_neon_vld3,
21603 Intrinsic::arm_neon_vld4};
21612 assert((Factor == 2 || Factor == 4) &&
21613 "expected interleave factor of 2 or 4 for MVE");
21615 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21616 Type *PtrTy = Builder.
getPtrTy(LI->getPointerAddressSpace());
21617 Type *Tys[] = {VecTy, PtrTy};
21631 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21636 VecTy->getNumElements() * Factor);
21642 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21644 unsigned Index = Indices[i];
21654 SubVecs[SV].push_back(SubVec);
21663 auto &SubVec = SubVecs[SVI];
21666 SVI->replaceAllUsesWith(WideVec);
21702 const APInt &GapMask)
const {
21704 "Invalid interleave factor");
21705 auto *SI = dyn_cast<StoreInst>(Store);
21709 "Unexpected mask on store");
21711 auto *VecTy = cast<FixedVectorType>(SVI->
getType());
21712 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21714 unsigned LaneLen = VecTy->getNumElements() / Factor;
21715 Type *EltTy = VecTy->getElementType();
21719 Align Alignment = SI->getAlign();
21736 Type *IntTy =
DL.getIntPtrType(EltTy);
21748 Value *BaseAddr = SI->getPointerOperand();
21750 if (NumStores > 1) {
21753 LaneLen /= NumStores;
21763 if (Subtarget->hasNEON()) {
21764 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21765 Intrinsic::arm_neon_vst3,
21766 Intrinsic::arm_neon_vst4};
21767 Type *PtrTy = Builder.
getPtrTy(SI->getPointerAddressSpace());
21768 Type *Tys[] = {PtrTy, SubVecTy};
21776 assert((Factor == 2 || Factor == 4) &&
21777 "expected interleave factor of 2 or 4 for MVE");
21779 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21780 Type *PtrTy = Builder.
getPtrTy(SI->getPointerAddressSpace());
21781 Type *Tys[] = {PtrTy, SubVecTy};
21786 for (
unsigned F = 0;
F < Factor;
F++) {
21794 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21797 if (StoreCount > 0)
21799 BaseAddr, LaneLen * Factor);
21804 for (
unsigned i = 0; i < Factor; i++) {
21805 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21806 if (Mask[IdxI] >= 0) {
21810 unsigned StartMask = 0;
21811 for (
unsigned j = 1; j < LaneLen; j++) {
21812 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21813 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21814 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21844 if (
auto *ST = dyn_cast<StructType>(Ty)) {
21845 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21849 Members += SubMembers;
21851 }
else if (
auto *AT = dyn_cast<ArrayType>(Ty)) {
21855 Members += SubMembers * AT->getNumElements();
21866 }
else if (
auto *VT = dyn_cast<VectorType>(Ty)) {
21873 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21875 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21877 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21890 return (Members > 0 && Members <= 4);
21896 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21898 return ABITypeAlign;
21903 assert(StackAlign &&
"data layout string is missing stack alignment");
21904 return std::min(ABITypeAlign, *StackAlign);
21913 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21923 return IsHA || IsIntArray;
21927 const Constant *PersonalityFn)
const {
21935 const Constant *PersonalityFn)
const {
21948void ARMTargetLowering::insertCopiesSplitCSR(
21952 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21962 RC = &ARM::GPRRegClass;
21963 else if (ARM::DPRRegClass.
contains(*
I))
21964 RC = &ARM::DPRRegClass;
21974 assert(Entry->getParent()->getFunction().hasFnAttribute(
21975 Attribute::NoUnwind) &&
21976 "Function should be nounwind in insertCopiesSplitCSR!");
21977 Entry->addLiveIn(*
I);
21982 for (
auto *Exit : Exits)
21984 TII->get(TargetOpcode::COPY), *
I)
21995 return Subtarget->hasMVEIntegerOps();
22000 auto *VTy = dyn_cast<FixedVectorType>(Ty);
22005 unsigned NumElements = VTy->getNumElements();
22012 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22013 return Subtarget->hasMVEFloatOps();
22018 return Subtarget->hasMVEIntegerOps() &&
22019 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22020 ScalarTy->isIntegerTy(32));
22032 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22034 if (TyWidth > 128) {
22039 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22041 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22042 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22043 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22044 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22045 Value *LowerSplitAcc =
nullptr;
22046 Value *UpperSplitAcc =
nullptr;
22049 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22050 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22054 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22056 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22059 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22066 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22069 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22071 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22072 {ConstRotation, InputB, InputA});
22077 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22080 ConstRotation = ConstantInt::get(IntTy, 0);
22082 ConstRotation = ConstantInt::get(IntTy, 1);
22084 if (!ConstRotation)
22087 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22088 {ConstHalving, ConstRotation, InputA, InputB});
unsigned const MachineRegisterInfo * MRI
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue LowerUADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue ConvertBooleanCarryToCarryFlag(SDValue BoolCarry, SelectionDAG &DAG)
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static const MCPhysReg GPRArgRegs[]
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)
constexpr MVT FlagsVT
Value type used for "flags" operands / results (either CPSR or FPSCR_NZCV).
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 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.
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
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)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
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.
loop Loop Strength Reduction
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
uint64_t IntrinsicInst * II
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
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 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 shouldSignReturnAddress() const
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
bool isTargetMachO() const
bool isTargetAEABI() const
bool supportsTailCall() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
bool hasFPARMv8Base() const
bool isTargetWindows() const
bool isGVIndirectSymbol(const GlobalValue *GV) const
True if the GV will be accessed via an indirect symbol.
const ARMTargetLowering * getTargetLowering() const override
bool isTargetDarwin() const
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool isTargetAndroid() const
bool isTargetCOFF() const
bool isTargetGNUAEABI() const
unsigned getPreferBranchLogAlignment() const
bool useNEONForSinglePrecisionFP() const
bool hasAnyDataBarrier() const
bool allowsUnalignedMem() const
bool isTargetMuslAEABI() const
Align getDualLoadStoreAlignment() const
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool isReadOnly(const GlobalValue *GV) const
unsigned getMaxSupportedInterleaveFactor() const override
Get the maximum supported factor for interleaved memory accesses.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
unsigned getNumInterleavedAccesses(VectorType *VecTy, const DataLayout &DL) const
Returns the number of interleaved accesses that will be generated when lowering accesses of the given...
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Align getABIAlignmentForCallingConv(Type *ArgTy, const DataLayout &DL) const override
Return the correct alignment for the current calling convention.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool shouldExpandCmpUsingSelects(EVT VT) const override
Should we expand [US]CMP nodes using two selects and two compares, or by doing arithmetic on boolean ...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
Function * getSSPStackGuardCheck(const Module &M) const override
If the target has a standard stack protection check function that performs validation and error handl...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void insertSSPDeclarations(Module &M) const override
Inserts necessary declarations for SSP (stack protection) purpose.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override
Return true if it is profitable to combine an XOR of a logical shift to create a logical shift of NOT...
bool ExpandInlineAsm(CallInst *CI) const override
This hook allows the target to expand an inline asm call to be explicit llvm code if it wants to.
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.
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
bool useLoadStackGuardNode(const Module &M) const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vldN intrinsic.
std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override
Return the largest legal super-reg register class of the register class for the specified type and it...
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
const char * getTargetNodeName(unsigned Opcode) const override
This method returns the name of a target specific DAG node.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool isVarArg) const
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
allowsMisalignedMemoryAccesses - Returns true if the target allows unaligned memory accesses of the s...
bool isLegalInterleavedAccessType(unsigned Factor, FixedVectorType *VecTy, Align Alignment, const DataLayout &DL) const
Returns true if VecTy is a legal interleaved access type.
bool isVectorLoadExtDesirable(SDValue ExtVal) const override
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, unsigned &Cost) const override
Return true if the target can combine store(extractelement VectorTy, Idx).
bool useSoftFloat() const override
bool alignLoopsWithOptSize() const override
Should loops be aligned even when the function is marked OptSize (but not MinSize).
SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const
bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override
Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail ...
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
This class represents an incoming formal argument to a Function.
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
LLVM_ABI bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
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.
const Function * getParent() const
Return the enclosing method, or null if none.
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
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
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.
Value * getCalledOperand() const
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.
This class represents an Operation in the Expression.
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)
Implements a dense probed hash-table based set.
Diagnostic information for unsupported feature in backend.
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.
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.
Value * CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
BasicBlock * GetInsertBlock() const
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Value * CreateTruncOrBitCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
std::optional< unsigned > getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const
Return the cycle for the given class and operand.
bool isEmpty() const
Returns true if there are no itineraries.
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
Class to represent integer types.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
static bool LowerToByteSwap(CallInst *CI)
Try to replace a call instruction with a call to a bswap intrinsic.
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.
unsigned getSchedClass() const
Return the scheduling class for this instruction.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
Wrapper class representing physical registers. Should be passed by value.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
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.
LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
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 '...
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.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
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.
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)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
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.
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.
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
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.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags)
Get the specified node if it's already available, or else return NULL.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
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 reserve(size_type NewNumEntries)
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
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
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
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.
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.
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.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
LLVM_ABI void dump() const
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Type * getArrayElementType() const
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(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.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
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.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
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 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...
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ SET_FPENV
Sets the current floating-point environment.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ 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.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ RESET_FPENV
Set floating-point environment to default state.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SET_FPMODE
Sets the current dynamic floating-point control modes.
@ 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 ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ RESET_FPMODE
Sets default dynamic floating-point control modes.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SET_ROUNDING
Set rounding mode.
@ 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...
@ BR
Control flow instructions. These all have token chains.
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ BR_JT
BR_JT - Jumptable branch.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ 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.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ 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...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ 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.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SMULO
Same for multiplication.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ 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.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ 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.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ 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.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ 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.
@ TRAP
TRAP - Trapping instruction.
@ 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.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ 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.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ 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.
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.
Reg
All possible values of the reg field in the ModR/M byte.
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.
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.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
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)
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.
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)
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)
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...
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
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.
@ Sub
Subtraction of integers.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
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...
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.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
static constexpr roundingMode rmTowardZero
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
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)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)