83#include "llvm/IR/IntrinsicsARM.h"
118#define DEBUG_TYPE "arm-isel"
121STATISTIC(NumOptimizedImms,
"Number of times immediates were optimized");
122STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
123STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
125 "Number of constants with their storage promoted into constant pools");
129 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
134 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
139 cl::desc(
"Maximum size of constant to promote into a constant pool"),
143 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
148 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
153 cl::desc(
"Maximum number of base-updates to check generating postindex."),
161 ARM::R0, ARM::R1, ARM::R2, ARM::R3
175void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
176 if (VT != PromotedLdStVT) {
185 if (ElemTy != MVT::f64)
189 if (ElemTy == MVT::i32) {
233void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
235 addTypeForNEON(VT, MVT::f64);
238void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
240 addTypeForNEON(VT, MVT::v2f64);
243void ARMTargetLowering::setAllExpand(
MVT VT) {
256void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
263void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
264 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
266 for (
auto VT : IntTypes) {
341 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
342 for (
auto VT : FloatTypes) {
416 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
417 for (
auto VT : LongTypes) {
434 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
435 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
436 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
453 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
462 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
463 for (
auto VT : pTypes) {
514 RegInfo(Subtarget->getRegisterInfo()),
515 Itins(Subtarget->getInstrItineraryData()) {
521 const Triple &TT = TM.getTargetTriple();
523 if (Subtarget->isThumb1Only())
528 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
529 Subtarget->hasFPRegs()) {
533 if (!Subtarget->hasVFP2Base()) {
534 setAllExpand(MVT::f32);
543 if (!Subtarget->hasFP64()) {
544 setAllExpand(MVT::f64);
554 if (Subtarget->hasFullFP16()) {
569 if (Subtarget->hasBF16()) {
571 setAllExpand(MVT::bf16);
572 if (!Subtarget->hasFullFP16())
586 addAllExtLoads(VT, InnerVT,
Expand);
595 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
598 if (!Subtarget->hasV8_1MMainlineOps())
601 if (!Subtarget->isThumb1Only())
610 if (Subtarget->hasMVEIntegerOps())
611 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
614 if (Subtarget->hasLOB()) {
618 if (Subtarget->hasNEON()) {
619 addDRTypeForNEON(MVT::v2f32);
620 addDRTypeForNEON(MVT::v8i8);
621 addDRTypeForNEON(MVT::v4i16);
622 addDRTypeForNEON(MVT::v2i32);
623 addDRTypeForNEON(MVT::v1i64);
625 addQRTypeForNEON(MVT::v4f32);
626 addQRTypeForNEON(MVT::v2f64);
627 addQRTypeForNEON(MVT::v16i8);
628 addQRTypeForNEON(MVT::v8i16);
629 addQRTypeForNEON(MVT::v4i32);
630 addQRTypeForNEON(MVT::v2i64);
632 if (Subtarget->hasFullFP16()) {
633 addQRTypeForNEON(MVT::v8f16);
634 addDRTypeForNEON(MVT::v4f16);
637 if (Subtarget->hasBF16()) {
638 addQRTypeForNEON(MVT::v8bf16);
639 addDRTypeForNEON(MVT::v4bf16);
643 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
683 if (Subtarget->hasNEON()) {
796 if (!Subtarget->hasVFP4Base()) {
805 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
814 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
823 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
831 if (Subtarget->hasMVEIntegerOps()) {
836 if (Subtarget->hasMVEFloatOps()) {
840 if (!Subtarget->hasFP64()) {
892 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
895 if (Subtarget->hasFullFP16()) {
903 if (!Subtarget->hasFP16()) {
932 if (!Subtarget->isThumb1Only()) {
951 if (TT.isTargetAEABI() && !Subtarget->allowsUnalignedMem()) {
963 if (!Subtarget->isThumb1Only()) {
972 if (Subtarget->hasDSP()) {
982 if (Subtarget->hasBaseDSP()) {
990 if (Subtarget->isThumb1Only()) {
994 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
995 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1010 if (Subtarget->hasMVEIntegerOps())
1014 if (Subtarget->isThumb1Only()) {
1020 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1034 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1043 if (Subtarget->hasPerfMon())
1047 if (!Subtarget->hasV6Ops())
1050 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1051 : Subtarget->hasDivideInARMMode();
1058 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1070 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1071 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1074 HasStandaloneRem =
false;
1101 if (TT.isOSWindows())
1108 InsertFencesForAtomic =
false;
1109 if (Subtarget->hasAnyDataBarrier() &&
1110 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1114 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1119 if (!Subtarget->hasAcquireRelease() ||
1122 InsertFencesForAtomic =
true;
1128 if (Subtarget->hasDataBarrier())
1129 InsertFencesForAtomic =
true;
1149 if (!InsertFencesForAtomic) {
1156 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1168 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1169 Subtarget->hasForced32BitAtomics()) {
1183 if (!Subtarget->hasV6Ops()) {
1189 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1190 !Subtarget->isThumb1Only()) {
1219 if (Subtarget->hasFullFP16()) {
1229 if (Subtarget->hasFullFP16())
1244 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1245 !Subtarget->isThumb1Only()) {
1252 if (!Subtarget->hasVFP4Base()) {
1258 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1260 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1268 if (!Subtarget->hasFP16()) {
1285 if (Subtarget->hasFPARMv8Base()) {
1295 if (Subtarget->hasFP64())
1299 if (Subtarget->hasNEON()) {
1309 if (Subtarget->hasFullFP16()) {
1346 if (Subtarget->hasNEON()) {
1358 if (Subtarget->hasV8Ops()) {
1368 if (Subtarget->hasFullFP16()) {
1391 if (TT.isOSWindows()) {
1408 if (Subtarget->hasMVEIntegerOps())
1411 if (Subtarget->hasV6Ops())
1413 if (Subtarget->isThumb1Only())
1416 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1417 Subtarget->isThumb2()) {
1423 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1424 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1446 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1454 return Subtarget->useSoftFloat();
1458 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1471std::pair<const TargetRegisterClass *, uint8_t>
1482 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1483 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1484 RRC = &ARM::DPRRegClass;
1489 if (Subtarget->useNEONForSinglePrecisionFP())
1492 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1493 case MVT::v4f32:
case MVT::v2f64:
1494 RRC = &ARM::DPRRegClass;
1498 RRC = &ARM::DPRRegClass;
1502 RRC = &ARM::DPRRegClass;
1506 return std::make_pair(RRC,
Cost);
1515 if (Subtarget->hasMVEIntegerOps())
1530 if (Subtarget->hasNEON()) {
1531 if (VT == MVT::v4i64)
1532 return &ARM::QQPRRegClass;
1533 if (VT == MVT::v8i64)
1534 return &ARM::QQQQPRRegClass;
1536 if (Subtarget->hasMVEIntegerOps()) {
1537 if (VT == MVT::v4i64)
1538 return &ARM::MQQPRRegClass;
1539 if (VT == MVT::v8i64)
1540 return &ARM::MQQQQPRRegClass;
1549 Align &PrefAlign)
const {
1556 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1568 unsigned NumVals =
N->getNumValues();
1572 for (
unsigned i = 0; i != NumVals; ++i) {
1573 EVT VT =
N->getValueType(i);
1574 if (VT == MVT::Glue || VT == MVT::Other)
1580 if (!
N->isMachineOpcode())
1588 if (
MCID.getNumDefs() == 0)
1590 if (!Itins->isEmpty() &&
1591 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1605 return Const->getZExtValue() == 16;
1613 return Const->getZExtValue() == 16;
1621 return Const->getZExtValue() == 16;
1690 bool isVarArg)
const {
1709 if (!Subtarget->isAAPCS_ABI())
1711 else if (Subtarget->isTargetHardFloat() && !isVarArg)
1717 if (!Subtarget->isAAPCS_ABI()) {
1718 if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() && !isVarArg)
1721 }
else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1730 bool isVarArg)
const {
1731 return CCAssignFnForNode(CC,
false, isVarArg);
1735 bool isVarArg)
const {
1736 return CCAssignFnForNode(CC,
true, isVarArg);
1743 bool isVarArg)
const {
1770 if (Subtarget->hasFullFP16()) {
1771 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1783 if (Subtarget->hasFullFP16()) {
1784 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1797SDValue ARMTargetLowering::LowerCallResult(
1801 SDValue ThisVal,
bool isCmseNSCall)
const {
1809 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1810 CCValAssign VA = RVLocs[i];
1814 if (i == 0 && isThisReturn) {
1816 "unexpected return calling convention register assignment");
1834 if (!Subtarget->isLittle())
1836 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1851 if (!Subtarget->isLittle())
1853 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1883 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1894std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1896 bool IsTailCall,
int SPDiff)
const {
1898 MachinePointerInfo DstInfo;
1918 return std::make_pair(DstAddr, DstInfo);
1927ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1940 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1943 int SrcFI = SrcFrameIdxNode->getIndex();
1944 int DstFI = DstFrameIdxNode->getIndex();
1946 "byval passed in non-fixed stack slot");
1968 if (SrcOffset == DstOffset)
1976 RegsToPassVector &RegsToPass,
1983 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1984 unsigned id = Subtarget->isLittle() ? 0 : 1;
1996 MachinePointerInfo DstInfo;
1997 std::tie(DstAddr, DstInfo) =
1998 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2015 SelectionDAG &DAG = CLI.
DAG;
2017 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2018 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2019 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2026 const CallBase *CB = CLI.
CB;
2029 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2031 MachineFunction::CallSiteInfo CSInfo;
2032 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2033 bool isThisReturn =
false;
2034 bool isCmseNSCall =
false;
2035 bool isSibCall =
false;
2036 bool PreferIndirect =
false;
2037 bool GuardWithBTI =
false;
2047 !Subtarget->noBTIAtReturnTwice())
2055 isCmseNSCall =
true;
2058 if (!Subtarget->supportsTailCall())
2074 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2075 count_if(GV->users(), [&BB](
const User *U) {
2076 return isa<Instruction>(U) &&
2077 cast<Instruction>(U)->getParent() == BB;
2084 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2098 "site marked musttail");
2101 unsigned NumBytes = CCInfo.getStackSize();
2110 if (isTailCall && !isSibCall) {
2111 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2112 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2117 assert(StackAlign &&
"data layout string is missing stack alignment");
2118 NumBytes =
alignTo(NumBytes, *StackAlign);
2123 SPDiff = NumReusableBytes - NumBytes;
2127 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2143 RegsToPassVector RegsToPass;
2152 DenseMap<unsigned, SDValue> ByValTemporaries;
2156 for (
const CCValAssign &VA : ArgLocs) {
2158 SDValue Src = OutVals[ArgIdx];
2159 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2161 if (!
Flags.isByVal())
2165 MachinePointerInfo DstInfo;
2166 std::tie(Dst, DstInfo) =
2167 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2168 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2170 if (Copy == NoCopy) {
2175 }
else if (Copy == CopyOnce) {
2179 ByValTemporaries[ArgIdx] = Src;
2181 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2185 int TempFrameIdx = MFI.CreateStackObject(
2186 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2194 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2195 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2197 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2198 ByValTemporaries[ArgIdx] = Temp;
2201 if (!ByValCopyChains.
empty())
2211 bool AfterFormalArgLoads =
false;
2215 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2217 ++i, ++realArgIdx) {
2218 CCValAssign &VA = ArgLocs[i];
2219 SDValue Arg = OutVals[realArgIdx];
2220 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2221 bool isByVal =
Flags.isByVal();
2241 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2243 if (ByValTempChain) {
2248 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2249 if (Outs[
I].
Flags.isByVal())
2257 FrameIndexSDNode *FIN =
2262 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2265 for (
const CCValAssign &VA : ArgLocs) {
2273 if (!IncomingLoad.
empty()) {
2281 AfterFormalArgLoads =
true;
2293 auto ArgVT = Outs[realArgIdx].ArgVT;
2294 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2312 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2313 StackPtr, MemOpChains, isTailCall, SPDiff);
2317 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2318 StackPtr, MemOpChains, isTailCall, SPDiff);
2322 MachinePointerInfo DstInfo;
2323 std::tie(DstAddr, DstInfo) =
2324 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2328 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2329 StackPtr, MemOpChains, isTailCall, SPDiff);
2331 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2332 Outs[0].VT == MVT::i32) {
2334 "unexpected calling convention register assignment");
2336 "unexpected use of 'returned'");
2337 isThisReturn =
true;
2342 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2343 }
else if (isByVal) {
2345 unsigned offset = 0;
2349 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2350 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2353 bool NeedsStackCopy;
2354 if (
auto It = ByValTemporaries.
find(realArgIdx);
2355 It != ByValTemporaries.
end()) {
2356 ByValSrc = It->second;
2357 NeedsStackCopy =
true;
2360 NeedsStackCopy = !isTailCall;
2364 if (CurByValIdx < ByValArgsCount) {
2365 unsigned RegBegin, RegEnd;
2366 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2370 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2374 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2377 RegsToPass.push_back(std::make_pair(j,
Load));
2382 offset = RegEnd - RegBegin;
2384 CCInfo.nextInRegsParam();
2389 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2392 MachinePointerInfo DstInfo;
2393 std::tie(Dst, DstInfo) =
2394 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2402 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2403 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2410 MachinePointerInfo DstInfo;
2411 std::tie(DstAddr, DstInfo) =
2412 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2419 if (!MemOpChains.
empty())
2425 for (
const auto &[
Reg,
N] : RegsToPass) {
2433 bool isDirect =
false;
2436 const Triple &
TT = TM.getTargetTriple();
2437 const GlobalValue *GVal =
nullptr;
2439 GVal =
G->getGlobal();
2440 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2442 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2443 bool isLocalARMFunc =
false;
2446 if (Subtarget->genLongCalls()) {
2448 if (isPIC && Subtarget->genExecuteOnly())
2450 "position-independent code is not supported");
2451 if (Subtarget->isROPI())
2458 if (Subtarget->genExecuteOnly()) {
2461 if (Subtarget->useMovt())
2484 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2490 const char *Sym = S->getSymbol();
2492 if (Subtarget->genExecuteOnly()) {
2495 if (Subtarget->useMovt())
2502 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
2508 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2513 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, GOTOffset, PICLabel);
2525 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2532 if (!PreferIndirect) {
2537 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2539 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2540 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2542 ARMISD::WrapperPIC, dl, PtrVt,
2549 }
else if (Subtarget->isTargetCOFF()) {
2550 assert(Subtarget->isTargetWindows() &&
2551 "Windows is the only supported COFF target");
2555 else if (!TM.shouldAssumeDSOLocal(GVal))
2562 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2571 const char *Sym = S->getSymbol();
2572 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2574 ARMConstantPoolValue *CPV =
2576 ARMPCLabelIndex, 4);
2578 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2583 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2590 assert(!isARMFunc && !isDirect &&
2591 "Cannot handle call to ARM function or direct call");
2595 "call to non-secure function would require "
2596 "passing arguments on stack",
2602 "call to non-secure function would return value through pointer",
2609 if (Subtarget->isThumb()) {
2611 CallOpc = ARMISD::t2CALL_BTI;
2612 else if (isCmseNSCall)
2613 CallOpc = ARMISD::tSECALL;
2614 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2615 CallOpc = ARMISD::CALL_NOLINK;
2617 CallOpc = ARMISD::CALL;
2619 if (!isDirect && !Subtarget->hasV5TOps())
2620 CallOpc = ARMISD::CALL_NOLINK;
2621 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2623 !Subtarget->hasMinSize())
2625 CallOpc = ARMISD::CALL_NOLINK;
2627 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2634 if (isTailCall && !isSibCall) {
2639 std::vector<SDValue>
Ops;
2640 Ops.push_back(Chain);
2641 Ops.push_back(Callee);
2649 for (
const auto &[
Reg,
N] : RegsToPass)
2653 const uint32_t *
Mask;
2654 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2662 isThisReturn =
false;
2668 assert(Mask &&
"Missing call preserved mask for calling convention");
2672 Ops.push_back(InGlue);
2685 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2699 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2705 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2706 InVals, isThisReturn,
2707 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2714void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2715 Align Alignment)
const {
2717 Alignment = std::max(Alignment,
Align(4));
2723 unsigned AlignInRegs = Alignment.
value() / 4;
2724 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2725 for (
unsigned i = 0; i < Waste; ++i)
2731 unsigned Excess = 4 * (ARM::R4 -
Reg);
2738 if (NSAAOffset != 0 &&
Size > Excess) {
2750 unsigned ByValRegBegin =
Reg;
2751 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2755 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2761 Size = std::max<int>(
Size - Excess, 0);
2769bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2775 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2776 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2777 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2778 const SelectionDAG &DAG = CLI.
DAG;
2783 assert(Subtarget->supportsTailCall());
2796 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2798 if (!(Subtarget->isThumb1Only() ||
2799 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2800 AddressRegisters.
insert(ARM::R12);
2801 for (
const CCValAssign &AL : ArgLocs)
2803 AddressRegisters.
erase(
AL.getLocReg());
2804 if (AddressRegisters.
empty()) {
2805 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2824 <<
" (guaranteed tail-call CC)\n");
2825 return CalleeCC == CallerCC;
2830 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2832 if (isCalleeStructRet != isCallerStructRet) {
2845 const GlobalValue *GV =
G->getGlobal();
2848 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2849 TT.isOSBinFormatMachO())) {
2866 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2867 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2868 if (CalleeCC != CallerCC) {
2869 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2870 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2879 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2887 const MachineRegisterInfo &MRI = MF.
getRegInfo();
2889 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2908 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2917 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2930 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2933 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2937 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2942 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2964 bool isLittleEndian = Subtarget->isLittle();
2967 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2976 "secure entry function would return value through pointer",
2981 for (
unsigned i = 0, realRVLocIdx = 0;
2983 ++i, ++realRVLocIdx) {
2984 CCValAssign &VA = RVLocs[i];
2987 SDValue Arg = OutVals[realRVLocIdx];
2988 bool ReturnF16 =
false;
2990 if (Subtarget->hasFullFP16() && Subtarget->isTargetHardFloat()) {
3023 auto RetVT = Outs[realRVLocIdx].ArgVT;
3045 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3049 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3055 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3067 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3069 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3074 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3084 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3110 !Subtarget->isMClass()) {
3111 if (Subtarget->isThumb1Only())
3118 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3121bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3122 if (
N->getNumValues() != 1)
3124 if (!
N->hasNUsesOfValue(1, 0))
3128 SDNode *
Copy = *
N->user_begin();
3132 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3134 TCChain =
Copy->getOperand(0);
3135 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3136 SDNode *VMov =
Copy;
3138 SmallPtrSet<SDNode*, 2>
Copies;
3139 for (SDNode *U : VMov->
users()) {
3147 for (SDNode *U : VMov->
users()) {
3148 SDValue UseChain =
U->getOperand(0);
3156 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3164 if (!
Copy->hasOneUse())
3171 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3173 TCChain =
Copy->getOperand(0);
3178 bool HasRet =
false;
3179 for (
const SDNode *U :
Copy->users()) {
3180 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3181 U->getOpcode() != ARMISD::INTRET_GLUE)
3193bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3194 if (!Subtarget->supportsTailCall())
3211 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3227 EVT PtrVT =
Op.getValueType();
3237 if (Subtarget->genExecuteOnly()) {
3242 auto GV =
new GlobalVariable(
3248 return LowerGlobalAddress(GA, DAG);
3254 if (Subtarget->isThumb1Only())
3255 CPAlign = std::max(CPAlign,
Align(4));
3261 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3268 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3277 unsigned ARMPCLabelIndex = 0;
3283 if (!IsPositionIndependent) {
3286 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3293 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3297 if (!IsPositionIndependent)
3300 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3328ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3331 "This function expects a Darwin target");
3336 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3342 MVT::i32,
DL, Chain, DescAddr,
3357 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3366 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3372ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3375 "Windows specific TLS lowering");
3399 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3407 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3408 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3414 MachinePointerInfo());
3421 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3434 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3436 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3438 ARMConstantPoolValue *CPV =
3449 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3456 TargetLowering::CallLoweringInfo CLI(DAG);
3461 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3462 return CallResult.first;
3471 const GlobalValue *GV = GA->
getGlobal();
3477 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3481 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3484 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3485 ARMConstantPoolValue *CPV =
3492 PtrVT, dl, Chain,
Offset,
3500 PtrVT, dl, Chain,
Offset,
3505 ARMConstantPoolValue *CPV =
3510 PtrVT, dl, Chain,
Offset,
3526 if (
TT.isOSDarwin())
3527 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3529 if (
TT.isOSWindows())
3530 return LowerGlobalTLSAddressWindows(
Op, DAG);
3533 assert(
TT.isOSBinFormatELF() &&
"Only ELF implemented here");
3539 return LowerToTLSGeneralDynamicModel(GA, DAG);
3542 return LowerToTLSExecModels(GA, DAG, model);
3551 while (!Worklist.
empty()) {
3559 if (!
I ||
I->getParent()->getParent() !=
F)
3588 if (!GVar || !GVar->hasInitializer() ||
3589 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3590 !GVar->hasLocalLinkage())
3595 auto *
Init = GVar->getInitializer();
3597 Init->needsDynamicRelocation())
3609 unsigned RequiredPadding = 4 - (
Size % 4);
3610 bool PaddingPossible =
3611 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3616 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3640 if (RequiredPadding != 4) {
3645 while (RequiredPadding--)
3657 ++NumConstpoolPromoted;
3658 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3663 if (!(GV = GA->getAliaseeObject()))
3666 return V->isConstant();
3675 return LowerGlobalAddressWindows(
Op, DAG);
3677 return LowerGlobalAddressELF(
Op, DAG);
3679 return LowerGlobalAddressDarwin(
Op, DAG);
3691 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3704 }
else if (Subtarget->isROPI() && IsRO) {
3709 }
else if (Subtarget->isRWPI() && !IsRO) {
3712 if (Subtarget->useMovt()) {
3715 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3717 ARMConstantPoolValue *CPV =
3720 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3734 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3735 if (Subtarget->useMovt())
3739 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3743 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3752 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3753 "ROPI/RWPI not currently supported for Darwin");
3758 if (Subtarget->useMovt())
3769 if (Subtarget->isGVIndirectSymbol(GV))
3778 "non-Windows COFF is not supported");
3779 assert(Subtarget->useMovt() &&
3780 "Windows on ARM expects to use movw/movt");
3781 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3782 "ROPI/RWPI not currently supported for Windows");
3789 else if (!TM.shouldAssumeDSOLocal(GV))
3812 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3813 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3814 Op.getOperand(1), Val);
3820 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3827 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3831SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3834 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3838 case Intrinsic::arm_gnu_eabi_mcount: {
3844 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3845 const uint32_t *
Mask =
3847 assert(Mask &&
"Missing call preserved mask for calling convention");
3852 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3856 if (Subtarget->isThumb())
3859 ARM::tBL_PUSHLR, dl, ResultTys,
3860 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3861 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3865 {ReturnAddress, Callee, RegisterMask, Chain}),
3874 unsigned IntNo =
Op.getConstantOperandVal(0);
3878 case Intrinsic::localaddress: {
3880 const auto *RegInfo = Subtarget->getRegisterInfo();
3881 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
3883 Op.getSimpleValueType());
3885 case Intrinsic::eh_recoverfp: {
3891 "llvm.eh.recoverfp must take a function as the first argument");
3892 const auto *RegInfo = Subtarget->getRegisterInfo();
3895 MachineBasicBlock &
MBB = *MF.
begin();
3901 case Intrinsic::thread_pointer: {
3903 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3905 case Intrinsic::arm_cls: {
3909 const SDValue &Operand =
Op.getOperand(1);
3910 const EVT VTy =
Op.getValueType();
3913 case Intrinsic::arm_cls64: {
3919 case Intrinsic::arm_neon_vcls:
3920 case Intrinsic::arm_mve_vcls: {
3923 const EVT VTy =
Op.getValueType();
3926 case Intrinsic::eh_sjlj_lsda: {
3928 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3933 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3934 ARMConstantPoolValue *CPV =
3938 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3943 if (IsPositionIndependent) {
3945 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3949 case Intrinsic::arm_neon_vabs:
3952 case Intrinsic::arm_neon_vabds:
3953 if (
Op.getValueType().isInteger())
3955 Op.getOperand(1),
Op.getOperand(2));
3957 case Intrinsic::arm_neon_vabdu:
3959 Op.getOperand(1),
Op.getOperand(2));
3960 case Intrinsic::arm_neon_vmulls:
3961 case Intrinsic::arm_neon_vmullu: {
3962 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3963 ? ARMISD::VMULLs : ARMISD::VMULLu;
3964 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3965 Op.getOperand(1),
Op.getOperand(2));
3967 case Intrinsic::arm_neon_vminnm:
3968 case Intrinsic::arm_neon_vmaxnm: {
3969 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3971 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3972 Op.getOperand(1),
Op.getOperand(2));
3974 case Intrinsic::arm_neon_vminu:
3975 case Intrinsic::arm_neon_vmaxu: {
3976 if (
Op.getValueType().isFloatingPoint())
3978 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3980 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3981 Op.getOperand(1),
Op.getOperand(2));
3983 case Intrinsic::arm_neon_vmins:
3984 case Intrinsic::arm_neon_vmaxs: {
3986 if (!
Op.getValueType().isFloatingPoint()) {
3987 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3989 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3990 Op.getOperand(1),
Op.getOperand(2));
3992 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3994 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3995 Op.getOperand(1),
Op.getOperand(2));
3997 case Intrinsic::arm_neon_vtbl1:
3998 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
3999 Op.getOperand(1),
Op.getOperand(2));
4000 case Intrinsic::arm_neon_vtbl2:
4001 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
4002 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4003 case Intrinsic::arm_mve_pred_i2v:
4004 case Intrinsic::arm_mve_pred_v2i:
4005 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
4007 case Intrinsic::arm_mve_vreinterpretq:
4008 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
4010 case Intrinsic::arm_mve_lsll:
4011 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
4012 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4013 case Intrinsic::arm_mve_asrl:
4014 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
4015 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4016 case Intrinsic::arm_mve_vsli:
4017 return DAG.
getNode(ARMISD::VSLIIMM, SDLoc(
Op),
Op->getVTList(),
4018 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4019 case Intrinsic::arm_mve_vsri:
4020 return DAG.
getNode(ARMISD::VSRIIMM, SDLoc(
Op),
Op->getVTList(),
4021 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4032 if (!Subtarget->hasDataBarrier()) {
4036 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4037 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4038 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
4048 }
else if (Subtarget->preferISHSTBarriers() &&
4057 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4065 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4067 return Op.getOperand(0);
4070 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4072 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4074 return Op.getOperand(0);
4076 unsigned isData =
Op.getConstantOperandVal(4);
4077 if (Subtarget->isThumb()) {
4079 isRead = ~isRead & 1;
4080 isData = ~isData & 1;
4083 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4098 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4106 const SDLoc &dl)
const {
4108 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4112 RC = &ARM::tGPRRegClass;
4114 RC = &ARM::GPRRegClass;
4128 MVT::i32, dl, Root, FIN,
4134 if (!Subtarget->isLittle())
4136 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4149 const Value *OrigArg,
4150 unsigned InRegsParamRecordIdx,
4151 int ArgOffset,
unsigned ArgSize)
const {
4165 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4166 unsigned RBegin, REnd;
4171 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4176 ArgOffset = -4 * (ARM::R4 - RBegin);
4186 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4190 MachinePointerInfo(OrigArg, 4 * i));
4195 if (!MemOps.
empty())
4204 unsigned TotalArgRegsSaveSize,
4205 bool ForceMutable)
const {
4207 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4216 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4220bool ARMTargetLowering::splitValueIntoRegisterParts(
4222 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4224 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4236SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4238 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4239 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4252SDValue ARMTargetLowering::LowerFormalArguments(
4259 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4268 unsigned CurArgIdx = 0;
4280 unsigned ArgRegBegin = ARM::R4;
4281 for (
const CCValAssign &VA : ArgLocs) {
4287 if (!
Flags.isByVal())
4291 unsigned RBegin, REnd;
4293 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4299 int lastInsIndex = -1;
4303 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4306 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4310 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4311 CCValAssign &VA = ArgLocs[i];
4312 if (Ins[VA.
getValNo()].isOrigArg()) {
4313 std::advance(CurOrigArg,
4314 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4315 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4326 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4333 MVT::f64, dl, Chain, FIN,
4336 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4344 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4348 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4349 RC = &ARM::HPRRegClass;
4350 else if (RegVT == MVT::f32)
4351 RC = &ARM::SPRRegClass;
4352 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4353 RegVT == MVT::v4bf16)
4354 RC = &ARM::DPRRegClass;
4355 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4356 RegVT == MVT::v8bf16)
4357 RC = &ARM::QPRRegClass;
4358 else if (RegVT == MVT::i32)
4360 : &ARM::GPRRegClass;
4397 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4406 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4412 if (index != lastInsIndex)
4414 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4420 if (
Flags.isByVal()) {
4421 assert(Ins[index].isOrigArg() &&
4422 "Byval arguments cannot be implicit");
4426 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4460 lastInsIndex = index;
4467 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4468 TotalArgRegsSaveSize);
4472 "secure entry function must not be variadic", dl.
getDebugLoc()));
4482 assert(StackAlign &&
"data layout string is missing stack alignment");
4483 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4492 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4501 return CFP->getValueAPF().isPosZero();
4504 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4505 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4508 return CFP->getValueAPF().isPosZero();
4511 Op->getValueType(0) == MVT::f64) {
4515 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4524 if (
Op->getFlags().hasNoSignedWrap())
4540 (isIntEqualitySetCC(CC) ||
4550 if (ST.isThumb1Only() || !
Op.hasOneUse())
4553 unsigned Opc =
Op.getOpcode();
4556 return ShiftAmt->getZExtValue() <= 31 ? 1 : 0;
4559 return ST.isThumb() ? 0 : 1;
4567 return ST.isThumb() ? 0 : 1;
4577 const SDLoc &dl)
const {
4579 unsigned C = RHSC->getZExtValue();
4637 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4641 unsigned Mask =
LHS.getConstantOperandVal(1);
4643 uint64_t RHSV = RHSC->getZExtValue();
4644 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4646 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4660 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4663 LHS.getConstantOperandVal(1) < 31) {
4664 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4674 unsigned CompareType;
4677 CompareType = ARMISD::CMP;
4682 CompareType = ARMISD::CMPZ;
4691 if (CompareType != ARMISD::CMPZ &&
isCMN(
RHS, CC, DAG)) {
4692 CompareType = ARMISD::CMN;
4694 }
else if (CompareType != ARMISD::CMPZ &&
isCMN(
LHS, CC, DAG)) {
4695 CompareType = ARMISD::CMN;
4709 if (CompareType == ARMISD::CMP)
4737 bool Signaling)
const {
4738 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4744 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4753std::pair<SDValue, SDValue>
4756 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4768 switch (
Op.getOpcode()) {
4820 return std::make_pair(
Value, OverflowCmp);
4833 return Cmp.getValue(1);
4861 return DAG.
getNode(ARMISD::CMOV,
DL, VT, Zero, One, ARMcc, Flags);
4873 EVT VT =
Op.getValueType();
4874 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4877 switch (
Op.getOpcode()) {
4891 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4897 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4900 ARMcc, OverflowCmp);
4910 EVT VT =
Op.getValueType();
4911 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4921 switch (
Op->getOpcode()) {
4923 NewOpcode = ARMISD::UQADD8b;
4926 NewOpcode = ARMISD::QADD8b;
4929 NewOpcode = ARMISD::UQSUB8b;
4932 NewOpcode = ARMISD::QSUB8b;
4937 switch (
Op->getOpcode()) {
4939 NewOpcode = ARMISD::UQADD16b;
4942 NewOpcode = ARMISD::QADD16b;
4945 NewOpcode = ARMISD::UQSUB16b;
4948 NewOpcode = ARMISD::QSUB16b;
4956 DAG.
getNode(NewOpcode, dl, MVT::i32,
4967 unsigned Opc =
Cond.getOpcode();
4969 if (
Cond.getResNo() == 1 &&
4977 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4978 EVT VT =
Op.getValueType();
4980 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4988 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4989 const ConstantSDNode *CMOVTrue =
4991 const ConstantSDNode *CMOVFalse =
4994 if (CMOVTrue && CMOVFalse) {
5000 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5002 False = SelectFalse;
5003 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5009 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5010 Cond.getOperand(3), DAG);
5020 bool &swpCmpOps,
bool &swpVselOps) {
5048 swpCmpOps = !swpCmpOps;
5049 swpVselOps = !swpVselOps;
5072 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5074 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5076 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5090 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5111 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5113 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5134 EVT VT =
Op.getValueType();
5156 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5169 int64_t PosVal = std::max(Val1, Val2);
5170 int64_t NegVal = std::min(Val1, Val2);
5182 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5185 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5217 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5222 if (*K != KTmp || V != VTmp)
5233bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5235 return !Subtarget->hasVFP2Base();
5237 return !Subtarget->hasFP64();
5239 return !Subtarget->hasFullFP16();
5247 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5255 if (TVal == ~FVal) {
5256 Opcode = ARMISD::CSINV;
5257 }
else if (TVal == ~FVal + 1) {
5258 Opcode = ARMISD::CSNEG;
5259 }
else if (TVal + 1 == FVal) {
5260 Opcode = ARMISD::CSINC;
5261 }
else if (TVal == FVal + 1) {
5262 Opcode = ARMISD::CSINC;
5265 InvertCond = !InvertCond;
5272 if (Opcode != ARMISD::CSINC &&
5276 InvertCond = !InvertCond;
5282 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5285 InvertCond = !InvertCond;
5292 EVT VT =
Op.getValueType();
5296 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5308 if (VT == MVT::i32 &&
5327 if (
Op.getValueType().isInteger()) {
5335 LHS.getValueType() ==
RHS.getValueType()) {
5336 EVT VT =
LHS.getValueType();
5342 Shift = DAG.
getNOT(dl, Shift, VT);
5354 if (
LHS.getValueType() == MVT::i32) {
5358 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5364 EVT VT =
Op.getValueType();
5365 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5369 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5374 if (!
RHS.getNode()) {
5380 if (
LHS.getValueType() == MVT::i32) {
5391 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5392 TrueVal.getValueType() == MVT::f32 ||
5393 TrueVal.getValueType() == MVT::f64)) {
5407 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5417 if (Subtarget->hasFPARMv8Base() &&
5419 (
TrueVal.getValueType() == MVT::f16 ||
5420 TrueVal.getValueType() == MVT::f32 ||
5421 TrueVal.getValueType() == MVT::f64)) {
5422 bool swpCmpOps =
false;
5423 bool swpVselOps =
false;
5437 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5440 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5450 if (!
N->hasOneUse())
5453 if (!
N->getNumValues())
5455 EVT VT =
Op.getValueType();
5456 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5473 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5474 Ld->getPointerInfo(), Ld->getAlign(),
5475 Ld->getMemOperand()->getFlags());
5491 SDValue Ptr = Ld->getBasePtr();
5493 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5494 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5499 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5500 Ld->getPointerInfo().getWithOffset(4),
5502 Ld->getMemOperand()->getFlags());
5520 bool LHSSeenZero =
false;
5522 bool RHSSeenZero =
false;
5524 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5535 if (
LHS.getValueType() == MVT::f32) {
5541 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5553 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5554 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5569 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5588 unsigned Opc =
Cond.getOpcode();
5590 !Subtarget->isThumb1Only();
5591 if (
Cond.getResNo() == 1 &&
5601 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5606 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5621 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5626 if (!
RHS.getNode()) {
5634 unsigned Opc =
LHS.getOpcode();
5636 !Subtarget->isThumb1Only();
5648 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5655 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5659 if (
LHS.getValueType() == MVT::i32) {
5662 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5665 SDNodeFlags
Flags =
Op->getFlags();
5666 if (
Flags.hasNoNaNs() &&
5671 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5685 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5699 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5702 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5707 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5708 Addr,
Op.getOperand(2), JTI);
5712 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5716 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5719 DAG.
getLoad(PTy, dl, Chain, Addr,
5722 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5727 EVT VT =
Op.getValueType();
5730 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5731 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5739 const EVT OpTy =
Op.getOperand(0).getValueType();
5740 if (
OpTy == MVT::v4f32)
5742 else if (
OpTy == MVT::v4f16 && HasFullFP16)
5744 else if (
OpTy == MVT::v8f16 && HasFullFP16)
5749 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5752 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5757 EVT VT =
Op.getValueType();
5761 bool IsStrict =
Op->isStrictFPOpcode();
5762 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5764 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5777 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5778 CallOptions, Loc, Chain);
5787 EVT VT =
Op.getValueType();
5789 EVT FromVT =
Op.getOperand(0).getValueType();
5791 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5793 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5794 Subtarget->hasFP64())
5796 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5797 Subtarget->hasFullFP16())
5799 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5800 Subtarget->hasMVEFloatOps())
5802 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5803 Subtarget->hasMVEFloatOps())
5806 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5823 EVT VT =
Op.getValueType();
5826 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5832 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5833 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5834 "Invalid type for custom lowering!");
5839 if (VT == MVT::v4f32)
5840 DestVecType = MVT::v4i32;
5841 else if (VT == MVT::v4f16 && HasFullFP16)
5842 DestVecType = MVT::v4i16;
5843 else if (VT == MVT::v8f16 && HasFullFP16)
5844 DestVecType = MVT::v8i16;
5850 switch (
Op.getOpcode()) {
5862 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5867 EVT VT =
Op.getValueType();
5871 bool IsStrict =
Op->isStrictFPOpcode();
5872 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5874 if (isUnsupportedFloatingType(VT)) {
5885 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5886 CallOptions, Loc, Chain);
5898 EVT VT =
Op.getValueType();
5902 bool UseNEON = !InGPR && Subtarget->hasNEON();
5909 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5916 if (SrcVT == MVT::f32) {
5919 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5922 }
else if (VT == MVT::f32)
5923 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5938 if (VT == MVT::f32) {
5950 if (SrcVT == MVT::f64)
5959 if (VT == MVT::f32) {
5972 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5980 EVT VT =
Op.getValueType();
5982 unsigned Depth =
Op.getConstantOperandVal(0);
5984 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5988 MachinePointerInfo());
5997 const ARMBaseRegisterInfo &ARI =
5998 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
6003 EVT VT =
Op.getValueType();
6005 unsigned Depth =
Op.getConstantOperandVal(0);
6010 MachinePointerInfo());
6018 return StringSwitch<Register>(
RegName)
6019 .Case(
"sp", ARM::SP)
6030 assert(
N->getValueType(0) == MVT::i64
6031 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6034 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6074 const APInt &APIntIndex = Index->getAPIntValue();
6076 NewIndex *= APIntIndex;
6105 EVT SrcVT =
Op.getValueType();
6106 EVT DstVT =
N->getValueType(0);
6108 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6109 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6110 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6113 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6114 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6115 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6122 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6134 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6142 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6144 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6146 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6166 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6175 EVT VT =
Op.getValueType();
6197 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6207 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6218 EVT VT =
Op.getValueType();
6239 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6260 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6312 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6340 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6370 EVT VT =
N->getValueType(0);
6371 if (VT.
isVector() && ST->hasNEON()) {
6380 if (ElemTy == MVT::i8) {
6388 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6391 unsigned NumBits = ElemTy.getSizeInBits();
6393 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6403 if (ElemTy == MVT::i64) {
6416 if (!ST->hasV6T2Ops())
6425 EVT VT =
N->getValueType(0);
6428 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6429 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6430 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6431 "Unexpected type for custom ctpop lowering");
6439 unsigned EltSize = 8;
6462 Op =
Op.getOperand(0);
6464 APInt SplatBits, SplatUndef;
6465 unsigned SplatBitSize;
6468 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6470 SplatBitSize > ElementBits)
6481 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6485 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6496 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6501 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6502 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6511 EVT VT =
N->getValueType(0);
6526 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6528 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6533 "unexpected vector shift opcode");
6535 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6536 unsigned VShiftOpc =
6537 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6538 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6544 EVT ShiftVT =
N->getOperand(1).getValueType();
6547 unsigned VShiftOpc =
6548 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6549 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6554 EVT VT =
N->getValueType(0);
6563 "Unknown shift to lower!");
6565 unsigned ShOpc =
N->getOpcode();
6566 if (ST->hasMVEIntegerOps()) {
6568 unsigned ShPartsOpc = ARMISD::LSLL;
6589 ShPartsOpc = ARMISD::LSRL;
6591 ShPartsOpc = ARMISD::ASRL;
6596 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6610 if (ST->isThumb1Only())
6615 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6619 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6623 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6631 bool Invert =
false;
6638 EVT VT =
Op.getValueType();
6646 assert(ST->hasMVEIntegerOps() &&
6647 "No hardware support for integer vector comparison!");
6649 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6670 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6674 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6684 switch (SetCCOpcode) {
6688 if (ST->hasMVEFloatOps()) {
6691 Invert =
true; [[fallthrough]];
6696 case ISD::SETLT: Swap =
true; [[fallthrough]];
6700 case ISD::SETLE: Swap =
true; [[fallthrough]];
6716 Result = DAG.
getNOT(dl, Result, VT);
6719 case ISD::SETUO: Invert =
true; [[fallthrough]];
6728 Result = DAG.
getNOT(dl, Result, VT);
6734 switch (SetCCOpcode) {
6737 if (ST->hasMVEIntegerOps()) {
6740 Invert =
true; [[fallthrough]];
6743 case ISD::SETLT: Swap =
true; [[fallthrough]];
6745 case ISD::SETLE: Swap =
true; [[fallthrough]];
6762 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6765 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6770 Result = DAG.
getNOT(dl, Result, VT);
6795 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6798 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6804 Result = DAG.
getNOT(dl, Result, VT);
6813 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6830 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6841 unsigned OpCmode,
Imm;
6852 switch (SplatBitSize) {
6857 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6860 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6865 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6866 if ((SplatBits & ~0xff) == 0) {
6872 if ((SplatBits & ~0xff00) == 0) {
6875 Imm = SplatBits >> 8;
6885 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6886 if ((SplatBits & ~0xff) == 0) {
6892 if ((SplatBits & ~0xff00) == 0) {
6895 Imm = SplatBits >> 8;
6898 if ((SplatBits & ~0xff0000) == 0) {
6901 Imm = SplatBits >> 16;
6904 if ((SplatBits & ~0xff000000) == 0) {
6907 Imm = SplatBits >> 24;
6914 if ((SplatBits & ~0xffff) == 0 &&
6915 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6918 Imm = SplatBits >> 8;
6926 if ((SplatBits & ~0xffffff) == 0 &&
6927 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6930 Imm = SplatBits >> 16;
6946 unsigned ImmMask = 1;
6948 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6949 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6951 }
else if ((SplatBits & BitMask) != 0) {
6960 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6974 EVT VT =
Op.getValueType();
6975 bool IsDouble = (VT == MVT::f64);
6981 if (
ST->genExecuteOnly()) {
6983 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6984 "Unexpected architecture");
7002 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
7007 if (!
ST->hasVFP3Base())
7012 if (IsDouble && !Subtarget->hasFP64())
7019 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7037 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7046 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7100 unsigned ExpectedElt =
Imm;
7101 for (
unsigned i = 1; i < NumElts; ++i) {
7105 if (ExpectedElt == NumElts)
7108 if (M[i] < 0)
continue;
7109 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7117 bool &ReverseVEXT,
unsigned &
Imm) {
7119 ReverseVEXT =
false;
7130 unsigned ExpectedElt =
Imm;
7131 for (
unsigned i = 1; i < NumElts; ++i) {
7135 if (ExpectedElt == NumElts * 2) {
7140 if (M[i] < 0)
continue;
7141 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7156 return VT == MVT::v8i8 && M.size() == 8;
7161 if (Mask.size() == Elements * 2)
7162 return Index / Elements;
7163 return Mask[Index] == 0 ? 0 : 1;
7193 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7201 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7203 for (
unsigned j = 0; j < NumElts; j += 2) {
7204 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7205 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7210 if (M.size() == NumElts*2)
7225 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7228 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7230 for (
unsigned j = 0; j < NumElts; j += 2) {
7231 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7232 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7237 if (M.size() == NumElts*2)
7257 if (M.size() != NumElts && M.size() != NumElts*2)
7260 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7262 for (
unsigned j = 0; j < NumElts; ++j) {
7263 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7268 if (M.size() == NumElts*2)
7287 if (M.size() != NumElts && M.size() != NumElts*2)
7290 unsigned Half = NumElts / 2;
7291 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7293 for (
unsigned j = 0; j < NumElts; j += Half) {
7294 unsigned Idx = WhichResult;
7295 for (
unsigned k = 0; k < Half; ++k) {
7296 int MIdx = M[i + j + k];
7297 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7304 if (M.size() == NumElts*2)
7328 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7331 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7333 unsigned Idx = WhichResult * NumElts / 2;
7334 for (
unsigned j = 0; j < NumElts; j += 2) {
7335 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7336 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7342 if (M.size() == NumElts*2)
7361 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7364 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7366 unsigned Idx = WhichResult * NumElts / 2;
7367 for (
unsigned j = 0; j < NumElts; j += 2) {
7368 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7369 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7375 if (M.size() == NumElts*2)
7388 unsigned &WhichResult,
7391 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7392 return ARMISD::VTRN;
7393 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7394 return ARMISD::VUZP;
7395 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7396 return ARMISD::VZIP;
7400 return ARMISD::VTRN;
7402 return ARMISD::VUZP;
7404 return ARMISD::VZIP;
7413 if (NumElts != M.size())
7417 for (
unsigned i = 0; i != NumElts; ++i)
7418 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7427 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7435 int Ofs = Top ? 1 : 0;
7436 int Upper = SingleSource ? 0 : NumElts;
7437 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7438 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7440 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7449 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7458 unsigned Offset = Top ? 0 : 1;
7459 unsigned N = SingleSource ? 0 : NumElts;
7460 for (
unsigned i = 0; i < NumElts; i += 2) {
7461 if (M[i] >= 0 && M[i] != (
int)i)
7463 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7472 if (NumElts != M.size())
7480 unsigned Off0 = rev ? NumElts / 2 : 0;
7481 unsigned Off1 = rev ? 0 : NumElts / 2;
7482 for (
unsigned i = 0; i < NumElts; i += 2) {
7483 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7485 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7501 if (!ST->hasMVEFloatOps())
7506 if (VT != MVT::v8f16)
7527 for (
unsigned i = 1; i < 4; i++) {
7542 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7554 if (!ST->hasMVEFloatOps())
7559 if (VT != MVT::v4f32)
7575 for (
unsigned i = 1; i < 4; i++) {
7586 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7598 Val =
N->getAsZExtVal();
7600 if (ST->isThumb1Only()) {
7601 if (Val <= 255 || ~Val <= 255)
7613 EVT VT =
Op.getValueType();
7615 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7619 unsigned BitsPerBool;
7623 }
else if (NumElts == 4) {
7626 }
else if (NumElts == 8) {
7629 }
else if (NumElts == 16) {
7640 return U.get().isUndef() || U.get() == FirstOp;
7644 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7648 unsigned Bits32 = 0;
7649 for (
unsigned i = 0; i < NumElts; ++i) {
7653 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7655 Bits32 |= BoolMask << (i * BitsPerBool);
7661 for (
unsigned i = 0; i < NumElts; ++i) {
7674 if (!ST->hasMVEIntegerOps())
7678 EVT VT =
Op.getValueType();
7688 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7692 for (
unsigned I = 2;
I < NumElts;
I++) {
7708 switch (
N->getOpcode()) {
7719 return N->getOperand(1).getNode() ==
Op;
7721 switch (
N->getConstantOperandVal(0)) {
7722 case Intrinsic::arm_mve_add_predicated:
7723 case Intrinsic::arm_mve_mul_predicated:
7724 case Intrinsic::arm_mve_qadd_predicated:
7725 case Intrinsic::arm_mve_vhadd:
7726 case Intrinsic::arm_mve_hadd_predicated:
7727 case Intrinsic::arm_mve_vqdmulh:
7728 case Intrinsic::arm_mve_qdmulh_predicated:
7729 case Intrinsic::arm_mve_vqrdmulh:
7730 case Intrinsic::arm_mve_qrdmulh_predicated:
7731 case Intrinsic::arm_mve_vqdmull:
7732 case Intrinsic::arm_mve_vqdmull_predicated:
7734 case Intrinsic::arm_mve_sub_predicated:
7735 case Intrinsic::arm_mve_qsub_predicated:
7736 case Intrinsic::arm_mve_vhsub:
7737 case Intrinsic::arm_mve_hsub_predicated:
7738 return N->getOperand(2).getNode() ==
Op;
7753 EVT VT =
Op.getValueType();
7761 APInt SplatBits, SplatUndef;
7762 unsigned SplatBitSize;
7764 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7771 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7773 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7774 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7775 : SplatBitSize == 16 ? MVT::v8i16
7779 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7782 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7783 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7788 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7792 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7796 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7798 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7802 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7806 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7810 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7816 if (
ST->hasMVEIntegerOps() &&
7817 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7818 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7819 : SplatBitSize == 16 ? MVT::v8i16
7823 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7836 bool isOnlyLowElement =
true;
7837 bool usesOnlyOneValue =
true;
7838 bool hasDominantValue =
false;
7843 DenseMap<SDValue, unsigned> ValueCounts;
7845 for (
unsigned i = 0; i < NumElts; ++i) {
7850 isOnlyLowElement =
false;
7854 unsigned &
Count = ValueCounts[
V];
7857 if (++
Count > (NumElts / 2)) {
7858 hasDominantValue =
true;
7862 if (ValueCounts.
size() != 1)
7863 usesOnlyOneValue =
false;
7864 if (!
Value.getNode() && !ValueCounts.
empty())
7867 if (ValueCounts.
empty())
7873 (VT != MVT::v8f16 ||
ST->hasFullFP16()))
7880 if (hasDominantValue && EltSize <= 32) {
7889 ConstantSDNode *constIndex;
7896 if (VT !=
Value->getOperand(0).getValueType()) {
7899 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7904 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7909 if (!usesOnlyOneValue) {
7912 for (
unsigned I = 0;
I < NumElts; ++
I) {
7917 Ops.push_back(
Op.getOperand(
I));
7927 assert(FVT == MVT::f32 || FVT == MVT::f16);
7928 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7929 for (
unsigned i = 0; i < NumElts; ++i)
7934 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7938 if (usesOnlyOneValue) {
7941 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7965 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7985 if (EltSize >= 32) {
7991 for (
unsigned i = 0; i < NumElts; ++i)
8004 (VT == MVT::v8f16 && !
ST->hasFullFP16())) {
8006 for (
unsigned i = 0 ; i < NumElts; ++i) {
8025 EVT VT =
Op.getValueType();
8028 struct ShuffleSourceInfo {
8030 unsigned MinElt = std::numeric_limits<unsigned>::max();
8031 unsigned MaxElt = 0;
8041 int WindowScale = 1;
8043 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8051 for (
unsigned i = 0; i < NumElts; ++i) {
8066 SDValue SourceVec =
V.getOperand(0);
8068 if (Source == Sources.
end())
8072 unsigned EltNo =
V.getConstantOperandVal(1);
8079 if (Sources.
size() > 2)
8085 for (
auto &Source : Sources) {
8086 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8087 if (SrcEltTy.
bitsLT(SmallestEltTy))
8088 SmallestEltTy = SrcEltTy;
8090 unsigned ResMultiplier =
8098 for (
auto &Src : Sources) {
8099 EVT SrcVT = Src.ShuffleVec.getValueType();
8103 if (SrcVTSize == VTSize)
8112 if (SrcVTSize < VTSize) {
8113 if (2 * SrcVTSize != VTSize)
8119 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8123 if (SrcVTSize != 2 * VTSize)
8126 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8131 if (Src.MinElt >= NumSrcElts) {
8136 Src.WindowBase = -NumSrcElts;
8137 }
else if (Src.MaxElt < NumSrcElts) {
8151 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8154 Src.WindowBase = -Src.MinElt;
8161 for (
auto &Src : Sources) {
8162 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8163 if (SrcEltTy == SmallestEltTy)
8166 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8168 Src.WindowBase *= Src.WindowScale;
8173 for (
auto Src : Sources)
8174 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8182 if (
Entry.isUndef())
8191 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8194 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8198 int *LaneMask = &
Mask[i * ResMultiplier];
8200 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8201 ExtractBase += NumElts * (Src - Sources.begin());
8202 for (
int j = 0;
j < LanesDefined; ++
j)
8203 LaneMask[j] = ExtractBase + j;
8209 assert(Sources.size() <= 2 &&
"Too many sources!");
8212 for (
unsigned i = 0; i < Sources.size(); ++i)
8219 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8241 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8261 unsigned PFIndexes[4];
8262 for (
unsigned i = 0; i != 4; ++i) {
8266 PFIndexes[i] = M[i];
8270 unsigned PFTableIndex =
8271 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8273 unsigned Cost = (PFEntry >> 30);
8279 bool ReverseVEXT, isV_UNDEF;
8280 unsigned Imm, WhichResult;
8283 if (EltSize >= 32 ||
8290 else if (Subtarget->hasNEON() &&
8295 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8298 else if (Subtarget->hasMVEIntegerOps() &&
8302 else if (Subtarget->hasMVEIntegerOps() &&
8316 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8317 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8318 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8321 if (LHSID == (1*9+2)*9+3)
return LHS;
8322 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8336 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8339 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8342 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8347 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8352 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8379 for (
int I : ShuffleMask)
8383 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8,
V1,
8386 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8,
V1, V2,
8392 EVT VT =
Op.getValueType();
8394 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8395 "Expect an v8i16/v16i8 type");
8401 std::vector<int> NewMask;
8405 NewMask.push_back(i);
8435 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8445 if (VT != MVT::v16i1)
8446 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8461 EVT VT =
Op.getValueType();
8465 assert(ST->hasMVEIntegerOps() &&
8466 "No support for vector shuffle of boolean predicates");
8476 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8492 "Expected identical vector type in expanded i1 shuffle!");
8496 PredAsVector2, ShuffleMask);
8501 if (VT == MVT::v2i1) {
8502 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8505 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8507 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8518 EVT VT =
Op.getValueType();
8522 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8523 "Unexpected vector type");
8525 int QuarterSize = NumElts / 4;
8534 for (
int i = 0; i <
Length; i++) {
8535 if (ShuffleMask[Start + i] >= 0) {
8536 if (ShuffleMask[Start + i] %
Length != i)
8538 MovIdx = ShuffleMask[Start + i] /
Length;
8546 for (
int i = 1; i <
Length; i++) {
8547 if (ShuffleMask[Start + i] >= 0 &&
8548 (ShuffleMask[Start + i] /
Length != MovIdx ||
8549 ShuffleMask[Start + i] %
Length != i))
8555 for (
int Part = 0; Part < 4; ++Part) {
8557 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8571 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8576 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8578 for (
int Part = 0; Part < 4; ++Part)
8579 for (
int i = 0; i < QuarterSize; i++)
8581 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8583 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8586 for (
int Part = 0; Part < 4; ++Part)
8602 EVT VT =
Op.getValueType();
8614 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8618 if (Mask[i] != i + BaseOffset) {
8619 if (OffElement == -1)
8625 return NonUndef > 2 && OffElement != -1;
8629 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8631 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8642 ShuffleMask[OffElement] < (
int)NumElts ?
V1 : V2,
8653 EVT VT =
Op.getValueType();
8657 if (ST->hasMVEIntegerOps() && EltSize == 1)
8668 if (EltSize <= 32) {
8672 if (Lane == -1) Lane = 0;
8676 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8683 bool IsScalarToVector =
true;
8684 for (
unsigned i = 1, e =
V1.getNumOperands(); i != e; ++i)
8685 if (!
V1.getOperand(i).isUndef()) {
8686 IsScalarToVector =
false;
8689 if (IsScalarToVector)
8690 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8692 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
V1,
8696 bool ReverseVEXT =
false;
8698 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT,
Imm)) {
8701 return DAG.
getNode(ARMISD::VEXT, dl, VT,
V1, V2,
8706 return DAG.
getNode(ARMISD::VREV64, dl, VT,
V1);
8708 return DAG.
getNode(ARMISD::VREV32, dl, VT,
V1);
8710 return DAG.
getNode(ARMISD::VREV16, dl, VT,
V1);
8722 unsigned WhichResult = 0;
8723 bool isV_UNDEF =
false;
8724 if (ST->hasNEON()) {
8726 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8733 if (ST->hasMVEIntegerOps()) {
8735 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2,
V1,
8738 return DAG.
getNode(ARMISD::VMOVN, dl, VT,
V1, V2,
8768 }) &&
"Unexpected shuffle index into UNDEF operand!");
8771 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8774 assert((WhichResult == 0) &&
8775 "In-place shuffle of concat can only have one result!");
8784 if (ST->hasMVEIntegerOps() && EltSize <= 32 &&
8785 (ST->hasFullFP16() || VT != MVT::v8f16)) {
8789 for (
bool Top : {
false,
true}) {
8790 for (
bool SingleSource : {
false,
true}) {
8791 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8796 SingleSource ?
V1 : V2);
8812 unsigned PFIndexes[4];
8813 for (
unsigned i = 0; i != 4; ++i) {
8814 if (ShuffleMask[i] < 0)
8817 PFIndexes[i] = ShuffleMask[i];
8821 unsigned PFTableIndex =
8822 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8824 unsigned Cost = (PFEntry >> 30);
8830 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8831 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8841 if (EltSize >= 32) {
8849 for (
unsigned i = 0; i < NumElts; ++i) {
8850 if (ShuffleMask[i] < 0)
8854 ShuffleMask[i] < (
int)NumElts ?
V1 : V2,
8862 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8866 if (ST->hasNEON() && VT == MVT::v8i8)
8870 if (ST->hasMVEIntegerOps())
8875 if (VT == MVT::v8f16 && !ST->hasFullFP16()) {
8877 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(0));
8879 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(1));
8881 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuf);
8889 EVT VecVT =
Op.getOperand(0).getValueType();
8892 assert(ST->hasMVEIntegerOps() &&
8893 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8896 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8897 unsigned Lane =
Op.getConstantOperandVal(2);
8898 unsigned LaneWidth =
8900 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8905 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8918 if (Subtarget->hasMVEIntegerOps() &&
8919 Op.getValueType().getScalarSizeInBits() == 1)
8943 IVecIn, IElt, Lane);
8952 EVT VecVT =
Op.getOperand(0).getValueType();
8955 assert(ST->hasMVEIntegerOps() &&
8956 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8959 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8960 unsigned Lane =
Op.getConstantOperandVal(1);
8961 unsigned LaneWidth =
8983 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8992 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8993 "Unexpected custom CONCAT_VECTORS lowering");
8995 "Unexpected custom CONCAT_VECTORS lowering");
8996 assert(ST->hasMVEIntegerOps() &&
8997 "CONCAT_VECTORS lowering only supported for MVE");
9000 EVT Op1VT =
V1.getValueType();
9001 EVT Op2VT = V2.getValueType();
9002 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9003 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9004 "Unexpected i1 concat operations!");
9017 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9022 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
9031 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9032 EVT NewVT = NewV.getValueType();
9033 EVT ConcatVT = ConVec.getValueType();
9034 unsigned ExtScale = 1;
9035 if (NewVT == MVT::v2f64) {
9036 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
9049 ConVec = ExtractInto(NewV1, ConVec, j);
9050 ConVec = ExtractInto(NewV2, ConVec, j);
9054 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
9060 while (ConcatOps.
size() > 1) {
9061 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
9064 ConcatOps[
I / 2] = ConcatPair(
V1, V2);
9068 return ConcatOps[0];
9073 EVT VT =
Op->getValueType(0);
9079 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9080 "unexpected CONCAT_VECTORS");
9101 EVT VT =
Op.getValueType();
9102 EVT Op1VT =
V1.getValueType();
9107 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9108 assert(ST->hasMVEIntegerOps() &&
9109 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9119 EVT SubVT = MVT::v4i32;
9121 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9131 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
9136 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9145 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9152 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9153 EVT VT =
N->getValueType(0);
9154 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9155 "Expected a vector i1 type!");
9157 EVT FromVT =
Op.getValueType();
9168 if (!Subtarget->hasMVEIntegerOps())
9171 EVT ToVT =
N->getValueType(0);
9214 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9216 EVT FromVT =
N->getOperand(0).getValueType();
9217 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9228 if (!Subtarget->hasMVEIntegerOps())
9233 EVT ToVT =
N->getValueType(0);
9234 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9237 EVT FromVT =
Op.getValueType();
9238 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9252 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9253 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9265 EVT VT =
N->getValueType(0);
9267 SDNode *BVN =
N->getOperand(0).getNode();
9272 unsigned HiElt = 1 - LoElt;
9277 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9293 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9294 SDNode *Elt =
N->getOperand(i).getNode();
9297 unsigned HalfSize = EltSize / 2;
9299 if (!
isIntN(HalfSize,
C->getSExtValue()))
9302 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9341 switch (OrigSimpleTy) {
9357 unsigned ExtOpcode) {
9380 if (ExtendedTy == LD->getMemoryVT())
9381 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9382 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9383 LD->getMemOperand()->getFlags());
9389 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9390 LD->getMemoryVT(), LD->getAlign(),
9391 LD->getMemOperand()->getFlags());
9404 N->getOperand(0)->getValueType(0),
9410 "Expected extending load");
9416 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9425 SDNode *BVN =
N->getOperand(0).getNode();
9427 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9435 EVT VT =
N->getValueType(0);
9441 for (
unsigned i = 0; i != NumElts; ++i) {
9442 const APInt &CInt =
N->getConstantOperandAPInt(i);
9451 unsigned Opcode =
N->getOpcode();
9453 SDNode *N0 =
N->getOperand(0).getNode();
9454 SDNode *N1 =
N->getOperand(1).getNode();
9462 unsigned Opcode =
N->getOpcode();
9464 SDNode *N0 =
N->getOperand(0).getNode();
9465 SDNode *N1 =
N->getOperand(1).getNode();
9475 EVT VT =
Op.getValueType();
9477 "unexpected type for custom-lowering ISD::MUL");
9478 SDNode *N0 =
Op.getOperand(0).getNode();
9479 SDNode *N1 =
Op.getOperand(1).getNode();
9480 unsigned NewOpc = 0;
9484 if (isN0SExt && isN1SExt)
9485 NewOpc = ARMISD::VMULLs;
9489 if (isN0ZExt && isN1ZExt)
9490 NewOpc = ARMISD::VMULLu;
9491 else if (isN1SExt || isN1ZExt) {
9495 NewOpc = ARMISD::VMULLs;
9498 NewOpc = ARMISD::VMULLu;
9502 NewOpc = ARMISD::VMULLu;
9508 if (VT == MVT::v2i64)
9525 "unexpected types for extended operands to VMULL");
9526 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9561 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9595 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9598 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9619 EVT VT =
Op.getValueType();
9620 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9621 "unexpected type for custom-lowering ISD::SDIV");
9628 if (VT == MVT::v8i8) {
9656 EVT VT =
Op.getValueType();
9657 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9658 "unexpected type for custom-lowering ISD::UDIV");
9665 if (VT == MVT::v8i8) {
9704 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9707 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9711 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9731 unsigned Opcode,
bool IsSigned) {
9732 EVT VT0 =
Op.getValue(0).getValueType();
9733 EVT VT1 =
Op.getValue(1).getValueType();
9735 bool InvertCarry = Opcode == ARMISD::SUBE;
9755 EVT VT =
Op.getValueType();
9756 assert((VT == MVT::i32 || VT == MVT::i64) &&
9757 "unexpected type for custom lowering DIV");
9763 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9765 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9772 for (
auto AI : {1, 0}) {
9774 Args.emplace_back(Operand,
9791ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9799 const bool MinSize =
ST.hasMinSize();
9800 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9801 :
ST.hasDivideInARMMode();
9805 if (
N->getOperand(0).getValueType().isVector())
9810 if (!(MinSize && HasDivide))
9823 if (Divisor.
sgt(128))
9831 assert(
Op.getValueType() == MVT::i32 &&
9832 "unexpected type for custom lowering DIV");
9835 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9838 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9844 if (
N->getValueType(0) == MVT::i32)
9845 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9848 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9852void ARMTargetLowering::ExpandDIV_Windows(
9857 assert(
Op.getValueType() == MVT::i64 &&
9858 "unexpected type for custom lowering DIV");
9873std::pair<SDValue, SDValue>
9874ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9880 EVT MemVT =
LD->getMemoryVT();
9881 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9885 unsigned AS =
LD->getAddressSpace();
9886 Align Alignment =
LD->getAlign();
9888 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9890 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9898 Opts, dl,
LD->getChain());
9923 EVT MemVT =
ST->getMemoryVT();
9924 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9928 unsigned AS =
ST->getAddressSpace();
9929 Align Alignment =
ST->getAlign();
9931 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9933 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9942 if (
ST->isTruncatingStore())
9947 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9948 dl,
ST->getChain());
9950 return CallResult.second;
9961 EVT MemVT = LD->getMemoryVT();
9962 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9963 MemVT == MVT::v16i1) &&
9964 "Expected a predicate type!");
9965 assert(MemVT ==
Op.getValueType());
9967 "Expected a non-extending load");
9968 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9982 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9984 LD->getMemOperand());
9990 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9991 if (MemVT != MVT::v16i1)
10000 EVT MemVT =
LD->getMemoryVT();
10002 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10003 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
10004 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10005 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10008 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
10009 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10014 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
10015 auto Pair = LowerAEABIUnalignedLoad(
SDValue(
N, 0), DAG);
10017 Results.push_back(Pair.first);
10018 Results.push_back(Pair.second);
10025 EVT MemVT = ST->getMemoryVT();
10026 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10027 MemVT == MVT::v16i1) &&
10028 "Expected a predicate type!");
10029 assert(MemVT == ST->getValue().getValueType());
10030 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10031 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10036 SDValue Build = ST->getValue();
10037 if (MemVT != MVT::v16i1) {
10050 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
10056 ST->getChain(), dl, GRP, ST->getBasePtr(),
10058 ST->getMemOperand());
10064 EVT MemVT =
ST->getMemoryVT();
10066 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10067 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
10068 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10069 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10070 SDNode *
N =
Op.getNode();
10083 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10084 MemVT,
ST->getMemOperand());
10085 }
else if (Subtarget->hasMVEIntegerOps() &&
10086 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10087 MemVT == MVT::v16i1))) {
10089 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
10090 return LowerAEABIUnalignedStore(
Op, DAG);
10097 (
N->getOpcode() == ARMISD::VMOVIMM &&
10103 MVT VT =
Op.getSimpleValueType();
10105 SDValue PassThru =
N->getPassThru();
10116 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10117 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10118 N->getExtensionType(),
N->isExpandingLoad());
10121 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
10123 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10130 if (!ST->hasMVEIntegerOps())
10134 unsigned BaseOpcode = 0;
10135 switch (
Op->getOpcode()) {
10151 unsigned NumActiveLanes = NumElts;
10153 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10154 NumActiveLanes == 2) &&
10155 "Only expected a power 2 vector size");
10159 while (NumActiveLanes > 4) {
10160 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10162 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10163 NumActiveLanes /= 2;
10167 if (NumActiveLanes == 4) {
10177 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10178 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10179 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10185 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10189 if (EltVT !=
Op->getValueType(0))
10196 if (!ST->hasMVEFloatOps())
10203 if (!ST->hasNEON())
10211 unsigned PairwiseIntrinsic = 0;
10212 switch (
Op->getOpcode()) {
10216 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10219 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10222 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10225 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10231 unsigned NumActiveLanes = NumElts;
10233 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10234 NumActiveLanes == 2) &&
10235 "Only expected a power 2 vector size");
10241 VT =
Lo.getValueType();
10243 NumActiveLanes /= 2;
10247 while (NumActiveLanes > 1) {
10249 NumActiveLanes /= 2;
10256 if (EltVT !=
Op.getValueType()) {
10257 unsigned Extend = 0;
10258 switch (
Op->getOpcode()) {
10270 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10315 const SDValue Ops[] = {RegClass, V0, SubReg0,
V1, SubReg1};
10321 SDLoc dl(V.getNode());
10322 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10332 assert(
N->getValueType(0) == MVT::i64 &&
10333 "AtomicCmpSwap on types less than 64 should be legal");
10342 ARM::CMP_SWAP_64,
SDLoc(
N),
10343 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10362 EVT VT =
Op.getValueType();
10371 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10373 Chain, IsSignaling);
10374 if (!
RHS.getNode()) {
10390 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10392 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10393 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10410 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10413 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10426 if (!IsSigned && Subtarget->isThumb1Only()) {
10444 Sub1Result, Sub1Result, Flags1);
10459 if (
Op.getValueType() != MVT::i32)
10473 unsigned Opcode = ARMISD::SUBC;
10482 bool CanUseAdd =
false;
10498 Opcode = ARMISD::ADDC;
10522 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10523 GTCondValue, Flags);
10527 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10528 LTCondValue, Flags);
10530 if (
Op.getValueType() != MVT::i32)
10538 switch (
Op.getOpcode()) {
10572 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10576 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10577 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10599 return LowerSET_FPMODE(
Op, DAG);
10601 return LowerRESET_FPMODE(
Op, DAG);
10605 !
Op.getValueType().isVector())
10606 return LowerDIV_Windows(
Op, DAG,
true);
10610 !
Op.getValueType().isVector())
10611 return LowerDIV_Windows(
Op, DAG,
false);
10627 return LowerALUO(
Op, DAG);
10635 EVT MemVT = LD->getMemoryVT();
10636 if (Subtarget->hasMVEIntegerOps() &&
10637 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10638 MemVT == MVT::v16i1))
10641 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10647 return LowerSTORE(
Op, DAG, Subtarget);
10672 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10681 return LowerSPONENTRY(
Op, DAG);
10683 return LowerFP_TO_BF16(
Op, DAG);
10684 case ARMISD::WIN__DBZCHK:
return SDValue();
10687 return LowerCMP(
Op, DAG);
10689 return LowerABS(
Op, DAG);
10694 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10695 Op.getOperand(1).getValueType() == MVT::bf16) &&
10696 "Expected custom lowering of rounding operations only for f16");
10699 {
Op.getOperand(0),
Op.getOperand(1)});
10700 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10701 {Ext.getValue(1), Ext.getValue(0)});
10708 unsigned IntNo =
N->getConstantOperandVal(0);
10710 if (IntNo == Intrinsic::arm_smlald)
10711 Opc = ARMISD::SMLALD;
10712 else if (IntNo == Intrinsic::arm_smlaldx)
10713 Opc = ARMISD::SMLALDX;
10714 else if (IntNo == Intrinsic::arm_smlsld)
10715 Opc = ARMISD::SMLSLD;
10716 else if (IntNo == Intrinsic::arm_smlsldx)
10717 Opc = ARMISD::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);
10776 "can only expand DIV on Windows");
10788 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10817 "ROPI/RWPI not currently supported with SjLj");
10826 bool isThumb = Subtarget->isThumb();
10827 bool isThumb2 = Subtarget->
isThumb2();
10830 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10836 : &ARM::GPRRegClass;
10942 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10945 MachineRegisterInfo *MRI = &MF->
getRegInfo();
10950 : &ARM::GPRnopcRegClass;
10954 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10955 unsigned MaxCSNum = 0;
10956 for (MachineBasicBlock &BB : *MF) {
10962 for (MachineInstr &
II : BB) {
10963 if (!
II.isEHLabel())
10966 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10967 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10969 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10970 for (
unsigned Idx : CallSiteIdxs) {
10971 CallSiteNumToLPad[Idx].push_back(&BB);
10972 MaxCSNum = std::max(MaxCSNum, Idx);
10979 std::vector<MachineBasicBlock*> LPadList;
10980 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10981 LPadList.reserve(CallSiteNumToLPad.
size());
10982 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10983 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10984 for (MachineBasicBlock *
MBB : MBBList) {
10985 LPadList.push_back(
MBB);
10990 assert(!LPadList.empty() &&
10991 "No landing pad destinations for the dispatch jump table!");
10994 MachineJumpTableInfo *JTI =
11001 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
11004 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
11006 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
11009 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
11013 MF->insert(MF->end(), DispatchBB);
11014 MF->insert(MF->end(), DispContBB);
11015 MF->insert(MF->end(), TrapBB);
11019 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11021 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
11025 MachineInstrBuilder MIB;
11026 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11028 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
11038 unsigned NumLPads = LPadList.size();
11039 if (Subtarget->isThumb2()) {
11041 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11047 if (NumLPads < 256) {
11048 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11050 .
addImm(LPadList.size())
11054 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11055 .
addImm(NumLPads & 0xFFFF)
11058 unsigned VReg2 = VReg1;
11059 if ((NumLPads & 0xFFFF0000) != 0) {
11061 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11067 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11073 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11079 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11084 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11091 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11095 }
else if (Subtarget->isThumb()) {
11097 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11103 if (NumLPads < 256) {
11104 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11109 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11111 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11114 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11115 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11118 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11122 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11128 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11134 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11141 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11146 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11152 MachineMemOperand *JTMMOLd =
11157 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11163 unsigned NewVReg6 = NewVReg5;
11164 if (IsPositionIndependent) {
11166 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11173 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11178 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11184 if (NumLPads < 256) {
11185 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11189 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11191 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11192 .
addImm(NumLPads & 0xFFFF)
11195 unsigned VReg2 = VReg1;
11196 if ((NumLPads & 0xFFFF0000) != 0) {
11198 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11204 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11209 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11211 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11214 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11215 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11218 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11223 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11235 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11241 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11245 MachineMemOperand *JTMMOLd =
11249 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11256 if (IsPositionIndependent) {
11257 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11262 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11269 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11270 for (MachineBasicBlock *CurMBB : LPadList) {
11271 if (SeenMBBs.
insert(CurMBB).second)
11278 for (MachineBasicBlock *BB : InvokeBBs) {
11282 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11283 while (!Successors.empty()) {
11284 MachineBasicBlock *SMBB = Successors.pop_back_val();
11286 BB->removeSuccessor(SMBB);
11292 BB->normalizeSuccProbs();
11299 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11300 if (!
II->isCall())
continue;
11302 DenseSet<unsigned> DefRegs;
11304 OI =
II->operands_begin(), OE =
II->operands_end();
11306 if (!OI->isReg())
continue;
11307 DefRegs.
insert(OI->getReg());
11310 MachineInstrBuilder MIB(*MF, &*
II);
11312 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11313 unsigned Reg = SavedRegs[i];
11314 if (Subtarget->isThumb2() &&
11315 !ARM::tGPRRegClass.contains(
Reg) &&
11316 !ARM::hGPRRegClass.contains(
Reg))
11318 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11320 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11332 for (MachineBasicBlock *MBBLPad : MBBLPads)
11333 MBBLPad->setIsEHPad(
false);
11336 MI.eraseFromParent();
11349static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11351 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11352 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11354 return LdSize == 4 ? ARM::tLDRi
11355 : LdSize == 2 ? ARM::tLDRHi
11356 : LdSize == 1 ? ARM::tLDRBi : 0;
11358 return LdSize == 4 ? ARM::t2LDR_POST
11359 : LdSize == 2 ? ARM::t2LDRH_POST
11360 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11361 return LdSize == 4 ? ARM::LDR_POST_IMM
11362 : LdSize == 2 ? ARM::LDRH_POST
11363 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11368static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11370 return StSize == 16 ? ARM::VST1q32wb_fixed
11371 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11373 return StSize == 4 ? ARM::tSTRi
11374 : StSize == 2 ? ARM::tSTRHi
11375 : StSize == 1 ? ARM::tSTRBi : 0;
11377 return StSize == 4 ? ARM::t2STR_POST
11378 : StSize == 2 ? ARM::t2STRH_POST
11379 : StSize == 1 ? ARM::t2STRB_POST : 0;
11380 return StSize == 4 ? ARM::STR_POST_IMM
11381 : StSize == 2 ? ARM::STRH_POST
11382 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11389 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11390 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11391 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11392 assert(LdOpc != 0 &&
"Should have a load opcode");
11399 }
else if (IsThumb1) {
11405 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11410 }
else if (IsThumb2) {
11430 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11431 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11432 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11433 assert(StOpc != 0 &&
"Should have a store opcode");
11435 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11440 }
else if (IsThumb1) {
11447 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11452 }
else if (IsThumb2) {
11453 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11459 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11474 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11480 unsigned SizeVal =
MI.getOperand(2).getImm();
11481 unsigned Alignment =
MI.getOperand(3).getImm();
11485 MachineRegisterInfo &MRI = MF->
getRegInfo();
11486 unsigned UnitSize = 0;
11490 bool IsThumb1 = Subtarget->isThumb1Only();
11491 bool IsThumb2 = Subtarget->isThumb2();
11492 bool IsThumb = Subtarget->isThumb();
11494 if (Alignment & 1) {
11496 }
else if (Alignment & 2) {
11501 Subtarget->hasNEON()) {
11502 if ((Alignment % 16 == 0) && SizeVal >= 16)
11504 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11513 bool IsNeon = UnitSize >= 8;
11514 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11516 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11517 : UnitSize == 8 ? &ARM::DPRRegClass
11520 unsigned BytesLeft = SizeVal % UnitSize;
11521 unsigned LoopSize = SizeVal - BytesLeft;
11523 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11527 unsigned srcIn = src;
11528 unsigned destIn = dest;
11529 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11534 IsThumb1, IsThumb2);
11536 IsThumb1, IsThumb2);
11544 for (
unsigned i = 0; i < BytesLeft; i++) {
11549 IsThumb1, IsThumb2);
11551 IsThumb1, IsThumb2);
11555 MI.eraseFromParent();
11581 MF->
insert(It, loopMBB);
11582 MF->
insert(It, exitMBB);
11585 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11596 if (Subtarget->useMovt()) {
11597 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11600 }
else if (Subtarget->genExecuteOnly()) {
11601 assert(IsThumb &&
"Non-thumb expected to have used movt");
11606 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11610 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11611 MachineMemOperand *CPMMO =
11635 MachineBasicBlock *entryBB = BB;
11650 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11658 IsThumb1, IsThumb2);
11660 IsThumb1, IsThumb2);
11664 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11670 MachineInstrBuilder MIB =
11672 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11681 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11690 auto StartOfExit = exitMBB->
begin();
11694 unsigned srcIn = srcLoop;
11695 unsigned destIn = destLoop;
11696 for (
unsigned i = 0; i < BytesLeft; i++) {
11700 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11701 IsThumb1, IsThumb2);
11702 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11703 IsThumb1, IsThumb2);
11708 MI.eraseFromParent();
11716 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11719 assert(TM.getTargetTriple().isOSWindows() &&
11720 "__chkstk is only supported on Windows");
11721 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11741 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11742 if (ChkStkLibcall == RTLIB::Unsupported)
11746 switch (TM.getCodeModel()) {
11788 MI.eraseFromParent();
11797 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11812 .
addReg(
MI.getOperand(0).getReg())
11820 MI.eraseFromParent();
11844 if (miI == BB->
end()) {
11846 if (Succ->isLiveIn(ARM::CPSR))
11852 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11865 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11872 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11879 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11882 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11883 .
addUse(TotalIterationsReg)
11890 return TotalIterationsReg;
11901 Register TotalIterationsReg,
bool IsMemcpy) {
11910 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11920 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11928 Register RemainingLoopIterationsReg =
11930 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11931 .
addUse(TotalIterationsReg)
11933 .
addUse(RemainingLoopIterationsReg)
11939 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11940 .
addUse(ElementCountReg)
11942 .
addUse(RemainingElementsReg)
11947 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11948 .
addUse(PredCounterPhiReg)
11953 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11954 .
addUse(PredCounterPhiReg)
11963 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11972 SrcValueReg = OpSrcReg;
11974 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11985 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11986 .
addUse(LoopCounterPhiReg)
11989 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11990 .
addUse(RemainingLoopIterationsReg)
12008 "Invalid call instruction for a KCFI check");
12011 switch (
MBBI->getOpcode()) {
12014 case ARM::BLX_pred:
12015 case ARM::BLX_noip:
12016 case ARM::BLX_pred_noip:
12018 TargetOp = &
MBBI->getOperand(0);
12020 case ARM::TCRETURNri:
12021 case ARM::TCRETURNrinotr12:
12022 case ARM::TAILJMPr:
12023 case ARM::TAILJMPr4:
12024 TargetOp = &
MBBI->getOperand(0);
12030 case ARM::tBLXr_noip:
12031 case ARM::tBX_CALL:
12032 TargetOp = &
MBBI->getOperand(2);
12035 case ARM::tTAILJMPr:
12036 TargetOp = &
MBBI->getOperand(0);
12042 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
12046 unsigned KCFICheckOpcode;
12047 if (Subtarget->isThumb()) {
12048 if (Subtarget->isThumb2()) {
12049 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
12051 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
12054 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
12068 bool isThumb2 = Subtarget->isThumb2();
12069 switch (
MI.getOpcode()) {
12076 case ARM::tLDR_postidx: {
12080 .
add(
MI.getOperand(2))
12081 .
add(
MI.getOperand(3))
12082 .
add(
MI.getOperand(4))
12083 .
add(
MI.getOperand(0))
12085 MI.eraseFromParent();
12089 case ARM::MVE_MEMCPYLOOPINST:
12090 case ARM::MVE_MEMSETLOOPINST: {
12120 Register OpDestReg =
MI.getOperand(0).getReg();
12121 Register OpSrcReg =
MI.getOperand(1).getReg();
12122 Register OpSizeReg =
MI.getOperand(2).getReg();
12142 if (TpExit == BB) {
12144 "block containing memcpy/memset Pseudo");
12154 genTPEntry(TpEntry, TpLoopBody, TpExit, OpSizeReg,
TII, dl, MRI);
12157 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12159 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12162 Properties.resetNoPHIs();
12174 MI.eraseFromParent();
12184 case ARM::t2STR_preidx:
12185 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12187 case ARM::t2STRB_preidx:
12188 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12190 case ARM::t2STRH_preidx:
12191 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12194 case ARM::STRi_preidx:
12195 case ARM::STRBi_preidx: {
12196 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12197 : ARM::STRB_PRE_IMM;
12199 unsigned Offset =
MI.getOperand(4).getImm();
12207 .
add(
MI.getOperand(0))
12208 .
add(
MI.getOperand(1))
12209 .
add(
MI.getOperand(2))
12211 .
add(
MI.getOperand(5))
12212 .
add(
MI.getOperand(6))
12214 MI.eraseFromParent();
12217 case ARM::STRr_preidx:
12218 case ARM::STRBr_preidx:
12219 case ARM::STRH_preidx: {
12221 switch (
MI.getOpcode()) {
12223 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12224 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12225 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12230 MI.eraseFromParent();
12234 case ARM::tMOVCCr_pseudo: {
12252 F->insert(It, copy0MBB);
12253 F->insert(It, sinkMBB);
12256 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12262 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12278 .
addImm(
MI.getOperand(3).getImm())
12279 .
addReg(
MI.getOperand(4).getReg());
12294 .
addReg(
MI.getOperand(1).getReg())
12296 .
addReg(
MI.getOperand(2).getReg())
12299 MI.eraseFromParent();
12304 case ARM::BCCZi64: {
12310 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12315 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12319 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12325 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12329 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12339 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12348 MI.eraseFromParent();
12352 case ARM::Int_eh_sjlj_setjmp:
12353 case ARM::Int_eh_sjlj_setjmp_nofp:
12354 case ARM::tInt_eh_sjlj_setjmp:
12355 case ARM::t2Int_eh_sjlj_setjmp:
12356 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12359 case ARM::Int_eh_sjlj_setup_dispatch:
12360 EmitSjLjDispatchBlock(
MI, BB);
12362 case ARM::COPY_STRUCT_BYVAL_I32:
12364 return EmitStructByval(
MI, BB);
12365 case ARM::WIN__CHKSTK:
12366 return EmitLowered__chkstk(
MI, BB);
12367 case ARM::WIN__DBZCHK:
12368 return EmitLowered__dbzchk(
MI, BB);
12384 if (!
Node->hasAnyUseOfValue(0)) {
12385 MI.getOperand(0).setIsDead(
true);
12387 if (!
Node->hasAnyUseOfValue(1)) {
12388 MI.getOperand(1).setIsDead(
true);
12392 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12394 : &ARM::GPRRegClass);
12401 if (
MI.getOpcode() == ARM::MEMCPY) {
12422 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12423 &&
"converted opcode should be the same except for cc_out"
12424 " (and, on Thumb1, pred)");
12432 if (Subtarget->isThumb1Only()) {
12433 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12434 MI.addOperand(
MI.getOperand(1));
12435 MI.removeOperand(1);
12439 for (
unsigned i =
MI.getNumOperands(); i--;) {
12441 if (
op.isReg() &&
op.isUse()) {
12444 MI.tieOperands(DefIdx, i);
12452 ccOutIdx =
MCID->getNumOperands() - 1;
12454 ccOutIdx =
MCID->getNumOperands() - 1;
12458 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12459 assert(!NewOpc &&
"Optional cc_out operand required");
12464 bool definesCPSR =
false;
12465 bool deadCPSR =
false;
12466 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12470 definesCPSR =
true;
12473 MI.removeOperand(i);
12477 if (!definesCPSR) {
12478 assert(!NewOpc &&
"Optional cc_out operand required");
12481 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12483 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12484 "expect uninitialized optional cc_out operand");
12486 if (!Subtarget->isThumb1Only())
12522 switch (
N->getOpcode()) {
12523 default:
return false;
12525 CC =
N->getOperand(0);
12547 EVT VT =
N->getValueType(0);
12548 CC =
N->getOperand(0);
12595 EVT VT =
N->getValueType(0);
12598 bool SwapSelectOps;
12600 NonConstantVal, DAG))
12606 OtherOp, NonConstantVal);
12612 CCOp, TrueVal, FalseVal);
12632 if (
N->getOpcode() == ARMISD::VUZP)
12636 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12651 if (!
N->getValueType(0).is64BitVector())
12659 EVT VT =
N->getValueType(0);
12698 EVT VT =
N->getValueType(0);
12704 Opcode = Intrinsic::arm_neon_vpaddls;
12706 Opcode = Intrinsic::arm_neon_vpaddlu;
12734 EVT VT =
N->getValueType(0);
12749 unsigned nextIndex = 0;
12800 Ops.push_back(Vec);
12817 return DAG.
getNode(ExtOp, dl, VT, tmp);
12848 if (SRA.getOpcode() !=
ISD::SRA) {
12855 if (Const->getZExtValue() != 31)
12860 if (SRA.getOperand(0) !=
Mul)
12864 SDLoc dl(AddcNode);
12865 unsigned Opcode = 0;
12870 Opcode = ARMISD::SMLALBB;
12871 Op0 =
Mul.getOperand(0);
12872 Op1 =
Mul.getOperand(1);
12874 Opcode = ARMISD::SMLALBT;
12875 Op0 =
Mul.getOperand(0);
12876 Op1 =
Mul.getOperand(1).getOperand(0);
12878 Opcode = ARMISD::SMLALTB;
12879 Op0 =
Mul.getOperand(0).getOperand(0);
12880 Op1 =
Mul.getOperand(1);
12882 Opcode = ARMISD::SMLALTT;
12883 Op0 =
Mul->getOperand(0).getOperand(0);
12884 Op1 =
Mul->getOperand(1).getOperand(0);
12900 SDValue resNode(AddcNode, 0);
12928 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12929 "Expect an ADDE or SUBE");
12933 "ADDE node has the wrong inputs");
12937 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12938 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12939 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12940 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12952 "Expect ADDC with two result values. First: i32");
12956 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12972 bool IsLeftOperandMUL =
false;
12977 IsLeftOperandMUL =
true;
12988 SDValue *LowAddSub =
nullptr;
12991 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12994 if (IsLeftOperandMUL)
12995 HiAddSub = &AddeSubeOp1;
12997 HiAddSub = &AddeSubeOp0;
13002 if (AddcSubcOp0 == MULOp.
getValue(0)) {
13003 LoMul = &AddcSubcOp0;
13004 LowAddSub = &AddcSubcOp1;
13006 if (AddcSubcOp1 == MULOp.
getValue(0)) {
13007 LoMul = &AddcSubcOp1;
13008 LowAddSub = &AddcSubcOp0;
13016 if (AddcSubcNode == HiAddSub->getNode() ||
13032 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13037 Ops.push_back(*HiAddSub);
13038 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
13039 FinalOpc = ARMISD::SMMLSR;
13041 FinalOpc = ARMISD::SMMLAR;
13046 return SDValue(AddeSubeNode, 0);
13047 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
13053 Ops.push_back(*LowAddSub);
13054 Ops.push_back(*HiAddSub);
13067 return SDValue(AddeSubeNode, 0);
13079 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13084 if (AddcNode->
getOpcode() != ARMISD::ADDC)
13088 SDNode *UmlalNode =
nullptr;
13127 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13132 SDNode* AddcNode =
N->getOperand(2).getNode();
13133 SDNode* AddeNode =
N->getOperand(3).getNode();
13134 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
13135 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
13141 {N->getOperand(0), N->getOperand(1),
13142 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13152 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13156 if (
LHS->getOpcode() == ARMISD::ADDE &&
13166 int32_t imm =
C->getSExtValue();
13167 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13170 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13172 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13187 int64_t imm =
C->getSExtValue();
13196 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13198 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13199 N->getOperand(0),
RHS,
N->getOperand(2));
13211 if (!Subtarget->hasMVEIntegerOps())
13224 SetCC =
N->getOperand(0);
13228 TrueVal =
N->getOperand(1);
13229 FalseVal =
N->getOperand(2);
13231 LHS =
N->getOperand(0);
13232 RHS =
N->getOperand(1);
13234 TrueVal =
N->getOperand(2);
13235 FalseVal =
N->getOperand(3);
13240 unsigned int Opcode = 0;
13244 Opcode = ARMISD::VMINVu;
13250 Opcode = ARMISD::VMINVs;
13256 Opcode = ARMISD::VMAXVu;
13262 Opcode = ARMISD::VMAXVs;
13269 switch (TrueVal->getOpcode()) {
13288 if (TrueVal !=
LHS || FalseVal !=
RHS)
13291 EVT LeftType =
LHS->getValueType(0);
13292 EVT RightType =
RHS->getValueType(0);
13295 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13299 if (VectorScalarType != MVT::i32)
13307 if (VectorScalarType != MVT::i32)
13320 EVT VT =
N->getValueType(0);
13328 Shft =
N->getOperand(0);
13335 Cmp.getOperand(0) !=
N->getOperand(1) ||
13336 Cmp.getOperand(1) !=
N->getOperand(2))
13338 Shft =
N->getOperand(1);
13350 ScalarType = MVT::i8;
13353 case (1 << 15) - 1:
13354 ScalarType = MVT::i16;
13357 case (1ULL << 31) - 1:
13358 ScalarType = MVT::i32;
13389 unsigned LegalLanes = 128 / (ShftAmt + 1);
13401 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13402 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13403 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13404 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13413 for (
unsigned I = 0;
I < NumParts; ++
I) {
13420 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13430 if (!Subtarget->hasMVEIntegerOps())
13435 if (
N->getOperand(0).getOpcode() == ARMISD::PREDICATE_CAST &&
13437 unsigned C =
N->getOperand(0).getConstantOperandVal(0);
13439 return N->getOperand(2);
13441 return N->getOperand(1);
13456 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13466 if (!Const || !Const->isOne())
13484 EVT VT =
N->getValueType(0);
13486 if (!Subtarget->hasMVEIntegerOps() ||
13515 Opc = Intrinsic::arm_mve_vctp64;
13518 Opc = Intrinsic::arm_mve_vctp32;
13521 Opc = Intrinsic::arm_mve_vctp16;
13524 Opc = Intrinsic::arm_mve_vctp8;
13578 EVT VT =
N->getValueType(0);
13584 switch (
Op.getOpcode()) {
13586 case ARMISD::VADDVs:
13587 case ARMISD::VADDVu:
13588 case ARMISD::VMLAVs:
13589 case ARMISD::VMLAVu:
13609 unsigned N0RedOp = 0;
13616 unsigned N1RedOp = 0;
13630 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13632 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13639 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13663 if (!BaseLocDecomp0.getBase() ||
13664 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13665 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13667 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13669 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13679 if (IsBefore < 0) {
13682 }
else if (IsBefore > 0) {
13695 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13705 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13715 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13717 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13724 if (!Subtarget->hasMVEIntegerOps())
13730 EVT VT =
N->getValueType(0);
13735 if (VT != MVT::i64)
13746 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13766 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13775 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13777 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13779 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13781 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13783 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13785 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13787 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13789 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13791 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13793 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13795 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13797 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13799 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13801 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13803 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13805 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13815 "Expected shift op");
13817 SDValue ShiftLHS =
N->getOperand(0);
13831 if (Subtarget->isThumb1Only()) {
13842 if (Const->getAPIntValue().ult(256))
13845 Const->getAPIntValue().sgt(-256))
13861 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13862 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13863 "Expected XOR(SHIFT) pattern");
13868 if (XorC && ShiftC) {
13869 unsigned MaskIdx, MaskLen;
13870 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13871 unsigned ShiftAmt = ShiftC->getZExtValue();
13872 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13873 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13874 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13875 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13885 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13887 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13888 "Expected shift-shift mask");
13890 if (!Subtarget->isThumb1Only())
13893 EVT VT =
N->getValueType(0);
13901 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13903 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13908 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps()) {
13909 if (Subtarget->isThumb1Only())
13923 return Subtarget->hasVFP2Base();
13925 return Subtarget->hasVFP2Base();
13927 return Subtarget->hasFP64();
13930 return Subtarget->hasMVEFloatOps();
13959 if (ST->isThumb1Only())
13963 for (
auto *U :
N->users()) {
13964 switch(U->getOpcode()) {
13982 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13983 U->getOperand(1).getOpcode() ==
ISD::SHL)
13993 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
14000 if (!C1ShlC2 || !C2)
14003 APInt C2Int = C2->getAPIntValue();
14004 APInt C1Int = C1ShlC2->getAPIntValue();
14006 if (C2Int.
uge(C2Width))
14012 if ((C1Int & Mask) != C1Int)
14019 auto LargeImm = [](
const APInt &
Imm) {
14020 unsigned Zeros =
Imm.countl_zero() +
Imm.countr_zero();
14021 return Imm.getBitWidth() - Zeros > 8;
14024 if (LargeImm(C1Int) || LargeImm(C2Int))
14036 SHL.dump();
N->dump());
14097 if (
Op.hasOneUse() && ShiftAmt &&
14098 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
14156 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14177 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14198 if (!Subtarget->hasVMLxForwarding())
14217 EVT VT =
N->getValueType(0);
14228 EVT VT =
N->getValueType(0);
14229 if (VT != MVT::v2i64)
14240 return Op->getOperand(0);
14254 And =
And->getOperand(0);
14259 Mask = Mask->getOperand(0);
14262 Mask.getValueType() != MVT::v4i32)
14268 return And->getOperand(0);
14273 if (
SDValue Op0 = IsSignExt(N0)) {
14274 if (
SDValue Op1 = IsSignExt(N1)) {
14275 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14276 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14277 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14280 if (
SDValue Op0 = IsZeroExt(N0)) {
14281 if (
SDValue Op1 = IsZeroExt(N1)) {
14282 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14283 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14284 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14296 EVT VT =
N->getValueType(0);
14297 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14308 if (VT != MVT::i32)
14315 int64_t MulAmt =
C->getSExtValue();
14318 ShiftAmt = ShiftAmt & (32 - 1);
14323 MulAmt >>= ShiftAmt;
14384 if (
N->getValueType(0) != MVT::i32)
14393 if (C1 == 255 || C1 == 65535)
14396 SDNode *N0 =
N->getOperand(0).getNode();
14410 if (!C2 || C2 >= 32)
14454 if (Trailing == C2 && C2 + C3 < 32) {
14467 if (Leading == C2 && C2 + C3 < 32) {
14495 EVT VT =
N->getValueType(0);
14499 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14502 APInt SplatBits, SplatUndef;
14503 unsigned SplatBitSize;
14505 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14506 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14507 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14508 SplatBitSize == 64) {
14515 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14517 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14542 if (!Subtarget->hasV6Ops() ||
14543 (Subtarget->isThumb() &&
14544 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14547 SDValue SRL = OR->getOperand(0);
14548 SDValue SHL = OR->getOperand(1);
14551 SRL = OR->getOperand(1);
14552 SHL = OR->getOperand(0);
14559 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14563 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14564 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14565 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14584 unsigned Opcode = 0;
14585 if (
isS16(OpS16, DAG))
14586 Opcode = ARMISD::SMULWB;
14588 Opcode = ARMISD::SMULWT;
14603 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14606 EVT VT =
N->getValueType(0);
14621 if (VT != MVT::i32)
14634 if (Mask == 0xffff)
14641 if ((Val & ~Mask) != Val)
14647 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14666 (Mask == ~Mask2)) {
14669 if (Subtarget->hasDSP() &&
14670 (Mask == 0xffff || Mask == 0xffff0000))
14676 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14683 (~Mask == Mask2)) {
14686 if (Subtarget->hasDSP() &&
14687 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14743 if (
N->getOpcode() == ARMISD::VCMP)
14745 else if (
N->getOpcode() == ARMISD::VCMPZ)
14753 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14760 EVT VT =
N->getValueType(0);
14765 auto IsFreelyInvertable = [&](
SDValue V) {
14766 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14772 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14790 if (AndOp.getOpcode() !=
ISD::AND)
14794 SDValue Mask = AndOp.getOperand(1);
14804 bool IsShiftRight =
false;
14807 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14808 IsShiftRight =
true;
14811 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14819 APInt RequiredMask = IsShiftRight
14822 if (MaskBits != RequiredMask)
14825 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14835 EVT VT =
N->getValueType(0);
14841 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14842 VT == MVT::v8i1 || VT == MVT::v16i1))
14845 APInt SplatBits, SplatUndef;
14846 unsigned SplatBitSize;
14848 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14849 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14850 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14851 SplatBitSize == 64) {
14858 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14860 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14880 (Subtarget->hasMVEIntegerOps() &&
14881 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14884 return ShiftInsert;
14888 return ShiftInsert;
14902 unsigned SplatBitSize;
14905 APInt SplatBits0, SplatBits1;
14909 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14910 HasAnyUndefs) && !HasAnyUndefs) {
14911 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14912 HasAnyUndefs) && !HasAnyUndefs) {
14917 SplatBits0 == ~SplatBits1) {
14925 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14945 if (CSINC.
getOpcode() != ARMISD::CSINC)
14947 if (CSINC.
getOpcode() == ARMISD::CSINC &&
14960 EVT VT =
N->getValueType(0);
14975 if (Subtarget->hasMVEIntegerOps()) {
15003 assert(
N->getOpcode() == ARMISD::BFI);
15006 ToMask =
~N->getConstantOperandAPInt(2);
15026 unsigned LastActiveBitInA =
A.countr_zero();
15027 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
15028 return LastActiveBitInA - 1 == FirstActiveBitInB;
15033 APInt ToMask, FromMask;
15038 if (V.getOpcode() != ARMISD::BFI)
15041 APInt NewToMask, NewFromMask;
15043 if (NewFrom != From)
15047 if ((NewToMask & ToMask).getBoolValue())
15072 unsigned InvMask =
N->getConstantOperandVal(2);
15076 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
15077 "undefined behavior");
15078 unsigned Mask = (1u << Width) - 1;
15080 if ((Mask & (~Mask2)) == 0)
15082 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
15089 APInt ToMask1, FromMask1;
15092 APInt ToMask2, FromMask2;
15098 APInt NewFromMask = FromMask1 | FromMask2;
15099 APInt NewToMask = ToMask1 | ToMask2;
15101 EVT VT =
N->getValueType(0);
15104 if (NewFromMask[0] == 0)
15107 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
15115 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
15116 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
15117 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
15119 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
15123 EVT VT =
N->getValueType(0);
15126 N->getOperand(1),
N->getOperand(2));
15138 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
15140 SDValue CSInc = Cmp->getOperand(0);
15150 if (CSInc.
getOpcode() == ARMISD::CSINC &&
15190 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15191 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15194 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15196 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15209 SDValue InDouble =
N->getOperand(0);
15210 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15224 SDValue BasePtr = LD->getBasePtr();
15226 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15227 LD->getAlign(), LD->getMemOperand()->getFlags());
15233 LD->getPointerInfo().getWithOffset(4),
15235 LD->getMemOperand()->getFlags());
15254 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15268 if (!Subtarget->
isLittle() && BVSwap)
15286 if (!Subtarget->
isLittle() && BVSwap)
15305 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15318 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15331 if (Copy.getValueType() == MVT::f32 &&
15333 bool HasGlue = Copy->getNumOperands() == 3;
15334 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15335 HasGlue ? Copy->getOperand(2) :
SDValue()};
15336 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15355 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15356 LN0->getMemoryVT() == MVT::i16) {
15359 LN0->getBasePtr(), LN0->getMemOperand());
15377 EVT VT =
N->getValueType(0);
15411 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15412 for (
unsigned i = 0; i < NumElts; ++i) {
15413 SDNode *Elt =
N->getOperand(i).getNode();
15430 if (
N->getNumOperands() == 2)
15436 EVT VT =
N->getValueType(0);
15442 for (
unsigned i = 0; i < NumElts; ++i) {
15468 EVT VT =
N->getValueType(0);
15476 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15481 Use->getValueType(0).isFloatingPoint())
15489 unsigned NumOfBitCastedElts = 0;
15491 unsigned NumOfRelevantElts = NumElts;
15492 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15497 ++NumOfBitCastedElts;
15501 --NumOfRelevantElts;
15505 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15523 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15528 V->getOperand(0).getValueType() == MVT::i32)
15530 V = V.getOperand(0);
15547 EVT VT =
N->getValueType(0);
15552 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15554 if (
Op->getOperand(0).getValueType() == VT)
15555 return Op->getOperand(0);
15556 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15563 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15570 if (
Op.getValueType() == MVT::i32) {
15581 EVT VT =
N->getValueType(0);
15586 if (ST->isLittle())
15590 if (
Op.getValueType() == VT)
15597 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15599 if (
Op->getOperand(0).getValueType() == VT)
15600 return Op->getOperand(0);
15601 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15609 if (!Subtarget->hasMVEIntegerOps())
15612 EVT VT =
N->getValueType(0);
15620 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15626 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15630 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15643 EVT VT =
N->getValueType(0);
15644 SDNode *Elt =
N->getOperand(1).getNode();
15659 Vec, V,
N->getOperand(2));
15669 EVT VT =
N->getValueType(0);
15697 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15698 isa<ConstantSDNode>(V->getOperand(1)) &&
15699 V->getConstantOperandVal(1) == Lane + 1 &&
15700 V->getOperand(0).getResNo() == ResNo;
15702 if (OtherIt == Op0->
users().
end())
15707 SDValue OtherExt(*OtherIt, 0);
15719 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15722 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15732 EVT VT =
N->getValueType(0);
15736 if (Op0->
getOpcode() == ARMISD::VDUP) {
15738 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15739 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15740 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15741 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15742 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15745 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15746 X =
X->getOperand(0);
15747 if (
X.getValueType() == VT)
15755 return Op0.
getOperand(
N->getConstantOperandVal(1));
15765 unsigned Offset =
N->getConstantOperandVal(1);
15767 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15777 unsigned Idx =
N->getConstantOperandVal(1);
15792 unsigned Lane =
N->getConstantOperandVal(1);
15820 EVT VT =
N->getValueType(0);
15823 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15825 Op.getOperand(0).getValueType().getScalarType())
15826 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15835 SDValue SubVec =
N->getOperand(1);
15836 uint64_t IdxVal =
N->getConstantOperandVal(2);
15847 if (IdxVal == 0 && Vec.
isUndef())
15853 (IdxVal != 0 && IdxVal != NumSubElts))
15884 ARMISD::VMOVN,
DL, VT,
15890 ARMISD::VMOVN,
DL, VT,
15926 EVT VT =
N->getValueType(0);
15937 unsigned HalfElts = NumElts/2;
15939 for (
unsigned n = 0; n < NumElts; ++n) {
15942 if (MaskElt < (
int)HalfElts)
15944 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15945 NewElt = HalfElts + MaskElt - NumElts;
15988 bool SimpleConstIncOnly,
15996 bool isLoadOp =
true;
15997 bool isLaneOp =
false;
16000 bool hasAlignment =
true;
16001 unsigned NewOpc = 0;
16002 unsigned NumVecs = 0;
16003 if (
Target.isIntrinsic) {
16004 unsigned IntNo =
N->getConstantOperandVal(1);
16008 case Intrinsic::arm_neon_vld1:
16012 case Intrinsic::arm_neon_vld2:
16016 case Intrinsic::arm_neon_vld3:
16020 case Intrinsic::arm_neon_vld4:
16024 case Intrinsic::arm_neon_vld1x2:
16027 hasAlignment =
false;
16029 case Intrinsic::arm_neon_vld1x3:
16032 hasAlignment =
false;
16034 case Intrinsic::arm_neon_vld1x4:
16037 hasAlignment =
false;
16039 case Intrinsic::arm_neon_vld2dup:
16043 case Intrinsic::arm_neon_vld3dup:
16047 case Intrinsic::arm_neon_vld4dup:
16051 case Intrinsic::arm_neon_vld2lane:
16056 case Intrinsic::arm_neon_vld3lane:
16061 case Intrinsic::arm_neon_vld4lane:
16066 case Intrinsic::arm_neon_vst1:
16071 case Intrinsic::arm_neon_vst2:
16072 NewOpc = ARMISD::VST2_UPD;
16076 case Intrinsic::arm_neon_vst3:
16081 case Intrinsic::arm_neon_vst4:
16082 NewOpc = ARMISD::VST4_UPD;
16086 case Intrinsic::arm_neon_vst2lane:
16092 case Intrinsic::arm_neon_vst3lane:
16098 case Intrinsic::arm_neon_vst4lane:
16104 case Intrinsic::arm_neon_vst1x2:
16108 hasAlignment =
false;
16110 case Intrinsic::arm_neon_vst1x3:
16114 hasAlignment =
false;
16116 case Intrinsic::arm_neon_vst1x4:
16120 hasAlignment =
false;
16125 switch (
N->getOpcode()) {
16161 VecTy =
N->getValueType(0);
16162 }
else if (
Target.isIntrinsic) {
16163 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16166 "Node has to be a load, a store, or an intrinsic!");
16167 VecTy =
N->getOperand(1).getValueType();
16175 if (isLaneOp || isVLDDUPOp)
16178 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16184 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16193 EVT AlignedVecTy = VecTy;
16213 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16214 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16225 Alignment =
Align(1);
16231 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16233 for (n = 0; n < NumResultVecs; ++n)
16234 Tys[n] = AlignedVecTy;
16235 Tys[n++] = MVT::i32;
16236 Tys[n] = MVT::Other;
16241 Ops.push_back(
N->getOperand(0));
16242 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16247 Ops.push_back(StN->getValue());
16251 unsigned LastOperand =
16252 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16253 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16254 Ops.push_back(
N->getOperand(i));
16262 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16273 for (
unsigned i = 0; i < NumResultVecs; ++i)
16278 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16279 SDValue &LdVal = NewResults[0];
16315 switch (
N->getOpcode()) {
16319 *Ptr =
N->getOperand(0);
16320 *CInc =
N->getOperand(1);
16327 *Ptr =
N->getOperand(1);
16328 *CInc =
N->getOperand(2);
16355 SDValue Addr =
N->getOperand(AddrOpIdx);
16366 unsigned ConstInc =
16371 if (BaseUpdates.
size() >= MaxBaseUpdates)
16392 unsigned UserOffset =
16395 if (!UserOffset || UserOffset <=
Offset)
16398 unsigned NewConstInc = UserOffset -
Offset;
16401 if (BaseUpdates.
size() >= MaxBaseUpdates)
16409 unsigned NumValidUpd = BaseUpdates.
size();
16410 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16421 return LHS.ConstInc <
RHS.ConstInc;
16450 unsigned IntNo =
N->getConstantOperandVal(1);
16451 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16453 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16476 bool isLoadOp =
true;
16477 unsigned NewOpc = 0;
16478 unsigned NumVecs = 0;
16482 case Intrinsic::arm_mve_vld2q:
16486 case Intrinsic::arm_mve_vld4q:
16490 case Intrinsic::arm_mve_vst2q:
16491 NewOpc = ARMISD::VST2_UPD;
16495 case Intrinsic::arm_mve_vst4q:
16496 NewOpc = ARMISD::VST4_UPD;
16505 VecTy =
N->getValueType(0);
16507 VecTy =
N->getOperand(3).getValueType();
16521 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16523 for (n = 0; n < NumResultVecs; ++n)
16525 Tys[n++] = MVT::i32;
16526 Tys[n] = MVT::Other;
16531 Ops.push_back(
N->getOperand(0));
16532 Ops.push_back(
N->getOperand(2));
16533 Ops.push_back(Inc);
16535 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16536 Ops.push_back(
N->getOperand(i));
16543 for (
unsigned i = 0; i < NumResultVecs; ++i)
16562 EVT VT =
N->getValueType(0);
16568 SDNode *VLD =
N->getOperand(0).getNode();
16571 unsigned NumVecs = 0;
16572 unsigned NewOpc = 0;
16574 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16577 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16580 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16592 if (
Use.getResNo() == NumVecs)
16595 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16596 VLDLaneNo !=
User->getConstantOperandVal(1))
16603 for (n = 0; n < NumVecs; ++n)
16605 Tys[n] = MVT::Other;
16615 unsigned ResNo =
Use.getResNo();
16617 if (ResNo == NumVecs)
16624 std::vector<SDValue> VLDDupResults;
16625 for (
unsigned n = 0; n < NumVecs; ++n)
16639 EVT VT =
N->getValueType(0);
16642 if (Subtarget->hasMVEIntegerOps()) {
16646 ExtractVT = MVT::i32;
16648 N->getOperand(0),
N->getOperand(1));
16660 Op =
Op.getOperand(0);
16661 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16665 unsigned EltSize =
Op.getScalarValueSizeInBits();
16667 unsigned Imm =
Op.getConstantOperandVal(0);
16683 if (Subtarget->hasMVEIntegerOps()) {
16686 if (
Op.getValueType() == MVT::f32)
16687 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16689 else if (
Op.getValueType() == MVT::f16)
16690 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16691 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16694 if (!Subtarget->hasNEON())
16701 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16702 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16703 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16708 LD->getMemoryVT(), LD->getMemOperand());
16719 EVT VT =
N->getValueType(0);
16741 assert(StVT != VT &&
"Cannot truncate to the same type");
16751 if (0 != (NumElems * FromEltSz) % ToEltSz)
16754 unsigned SizeRatio = FromEltSz / ToEltSz;
16759 NumElems * SizeRatio);
16765 for (
unsigned i = 0; i < NumElems; ++i)
16779 MVT StoreType = MVT::i8;
16781 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16801 for (
unsigned I = 0;
I <
E;
I++) {
16832 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16835 unsigned NumElements = 4;
16852 unsigned Off0 = Rev ? NumElts : 0;
16853 unsigned Off1 = Rev ? 0 : NumElts;
16855 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16856 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16858 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16866 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16886 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16897 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16901 NewToVT, Alignment, MMOFlags, AAInfo);
16934 unsigned NewOffset =
16942 NewToVT, Alignment, MMOFlags, AAInfo);
16964 {Extract.getOperand(0), Extract.getOperand(1)});
16995 if (Subtarget->hasNEON())
16999 if (Subtarget->hasMVEFloatOps())
17003 if (Subtarget->hasMVEIntegerOps()) {
17077 if (!Subtarget->hasNEON())
17081 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
17089 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
17091 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
17092 uint32_t IntBits = IntTy.getSizeInBits();
17093 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17094 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17105 if (
C == -1 ||
C == 0 ||
C > 32)
17110 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
17111 Intrinsic::arm_neon_vcvtfp2fxu;
17114 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
17117 if (IntBits < FloatBits)
17125 if (!Subtarget->hasMVEFloatOps())
17133 EVT VT =
N->getValueType(0);
17138 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
17140 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
17142 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
17143 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
17145 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17158 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17169 EVT VT =
N->getValueType(0);
17172 if (!
N->getFlags().hasAllowReassociation())
17179 unsigned Opc =
A.getConstantOperandVal(0);
17180 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17185 A.getOperand(3),
A.getOperand(4));
17217 if (!Subtarget->hasNEON())
17221 unsigned OpOpcode =
Op.getNode()->getOpcode();
17222 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17226 SDValue ConstVec =
N->getOperand(1);
17230 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17232 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17233 uint32_t IntBits = IntTy.getSizeInBits();
17234 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17235 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17255 int32_t
C = IntVal.exactLogBase2();
17256 if (
C == -1 ||
C == 0 ||
C > 32)
17262 if (IntBits < FloatBits)
17264 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17266 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17267 : Intrinsic::arm_neon_vcvtfxu2fp;
17275 if (!ST->hasMVEIntegerOps())
17279 EVT ResVT =
N->getValueType(0);
17307 EVT AVT =
A.getValueType();
17313 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17314 EVT AVT =
A.getValueType();
17324 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17325 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17328 if (ExtTypeMatches(
A, ExtTypes))
17329 return ExtendIfNeeded(
A, ExtendCode);
17332 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17342 if (ExtTypeMatches(
A, ExtTypes))
17343 return ExtendIfNeeded(
A, ExtendCode);
17346 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17356 if (ResVT != RetTy)
17359 if (
Mul->getOpcode() == ExtendCode &&
17360 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17362 Mul =
Mul->getOperand(0);
17371 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17372 A = ExtendIfNeeded(
A, ExtendCode);
17373 B = ExtendIfNeeded(
B, ExtendCode);
17378 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17391 if (
Mul->getOpcode() == ExtendCode &&
17392 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17394 Mul =
Mul->getOperand(0);
17403 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17404 A = ExtendIfNeeded(
A, ExtendCode);
17405 B = ExtendIfNeeded(
B, ExtendCode);
17416 EVT VT =
Ops[0].getValueType();
17417 if (VT == MVT::v16i8) {
17418 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17419 "Unexpected illegal long reduction opcode");
17420 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17432 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17445 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17447 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17448 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17450 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17451 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17453 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17456 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17459 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17463 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17466 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17469 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17472 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17475 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17478 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17481 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17483 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17485 return Create64bitNode(ARMISD::VADDLVs, {
A});
17487 return Create64bitNode(ARMISD::VADDLVu, {
A});
17490 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17493 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17496 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17498 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17500 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17502 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17505 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17508 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17515 Op =
Op->getOperand(1);
17517 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17519 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17536 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17538 if (!Shuf || !Shuf->getOperand(1).isUndef())
17543 APInt SetElts(Mask.size(), 0);
17544 for (
int E : Mask) {
17552 if (
N->getNumOperands() != VecOp + 1) {
17554 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17560 if (
Op.getValueType().isVector())
17561 Ops.push_back(
Op.getOperand(0));
17572 unsigned IsTop =
N->getConstantOperandVal(2);
17579 if (Op0->
isUndef() && !IsTop)
17584 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17585 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17593 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17595 APInt Op0DemandedElts =
17596 IsTop ? Op1DemandedElts
17611 unsigned IsTop =
N->getConstantOperandVal(2);
17613 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17614 APInt Op0DemandedElts =
17626 EVT VT =
N->getValueType(0);
17633 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17634 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17638 LHS.getOperand(0),
RHS.getOperand(0));
17653 int ShiftAmt =
C->getSExtValue();
17654 if (ShiftAmt == 0) {
17660 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17661 unsigned NewOpcode =
17662 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17677 unsigned IntNo =
N->getConstantOperandVal(0);
17688 case Intrinsic::arm_neon_vshifts:
17689 case Intrinsic::arm_neon_vshiftu:
17690 case Intrinsic::arm_neon_vrshifts:
17691 case Intrinsic::arm_neon_vrshiftu:
17692 case Intrinsic::arm_neon_vrshiftn:
17693 case Intrinsic::arm_neon_vqshifts:
17694 case Intrinsic::arm_neon_vqshiftu:
17695 case Intrinsic::arm_neon_vqshiftsu:
17696 case Intrinsic::arm_neon_vqshiftns:
17697 case Intrinsic::arm_neon_vqshiftnu:
17698 case Intrinsic::arm_neon_vqshiftnsu:
17699 case Intrinsic::arm_neon_vqrshiftns:
17700 case Intrinsic::arm_neon_vqrshiftnu:
17701 case Intrinsic::arm_neon_vqrshiftnsu: {
17702 EVT VT =
N->getOperand(1).getValueType();
17704 unsigned VShiftOpc = 0;
17707 case Intrinsic::arm_neon_vshifts:
17708 case Intrinsic::arm_neon_vshiftu:
17710 VShiftOpc = ARMISD::VSHLIMM;
17713 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17714 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17715 : ARMISD::VSHRuIMM);
17720 case Intrinsic::arm_neon_vrshifts:
17721 case Intrinsic::arm_neon_vrshiftu:
17726 case Intrinsic::arm_neon_vqshifts:
17727 case Intrinsic::arm_neon_vqshiftu:
17732 case Intrinsic::arm_neon_vqshiftsu:
17737 case Intrinsic::arm_neon_vrshiftn:
17738 case Intrinsic::arm_neon_vqshiftns:
17739 case Intrinsic::arm_neon_vqshiftnu:
17740 case Intrinsic::arm_neon_vqshiftnsu:
17741 case Intrinsic::arm_neon_vqrshiftns:
17742 case Intrinsic::arm_neon_vqrshiftnu:
17743 case Intrinsic::arm_neon_vqrshiftnsu:
17755 case Intrinsic::arm_neon_vshifts:
17756 case Intrinsic::arm_neon_vshiftu:
17759 case Intrinsic::arm_neon_vrshifts:
17760 VShiftOpc = ARMISD::VRSHRsIMM;
17762 case Intrinsic::arm_neon_vrshiftu:
17763 VShiftOpc = ARMISD::VRSHRuIMM;
17765 case Intrinsic::arm_neon_vrshiftn:
17766 VShiftOpc = ARMISD::VRSHRNIMM;
17768 case Intrinsic::arm_neon_vqshifts:
17769 VShiftOpc = ARMISD::VQSHLsIMM;
17771 case Intrinsic::arm_neon_vqshiftu:
17772 VShiftOpc = ARMISD::VQSHLuIMM;
17774 case Intrinsic::arm_neon_vqshiftsu:
17775 VShiftOpc = ARMISD::VQSHLsuIMM;
17777 case Intrinsic::arm_neon_vqshiftns:
17778 VShiftOpc = ARMISD::VQSHRNsIMM;
17780 case Intrinsic::arm_neon_vqshiftnu:
17781 VShiftOpc = ARMISD::VQSHRNuIMM;
17783 case Intrinsic::arm_neon_vqshiftnsu:
17784 VShiftOpc = ARMISD::VQSHRNsuIMM;
17786 case Intrinsic::arm_neon_vqrshiftns:
17787 VShiftOpc = ARMISD::VQRSHRNsIMM;
17789 case Intrinsic::arm_neon_vqrshiftnu:
17790 VShiftOpc = ARMISD::VQRSHRNuIMM;
17792 case Intrinsic::arm_neon_vqrshiftnsu:
17793 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17798 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17799 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17802 case Intrinsic::arm_neon_vshiftins: {
17803 EVT VT =
N->getOperand(1).getValueType();
17805 unsigned VShiftOpc = 0;
17808 VShiftOpc = ARMISD::VSLIIMM;
17809 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17810 VShiftOpc = ARMISD::VSRIIMM;
17816 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17817 N->getOperand(1),
N->getOperand(2),
17821 case Intrinsic::arm_neon_vqrshifts:
17822 case Intrinsic::arm_neon_vqrshiftu:
17826 case Intrinsic::arm_neon_vbsl: {
17828 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17829 N->getOperand(2),
N->getOperand(3));
17831 case Intrinsic::arm_mve_vqdmlah:
17832 case Intrinsic::arm_mve_vqdmlash:
17833 case Intrinsic::arm_mve_vqrdmlah:
17834 case Intrinsic::arm_mve_vqrdmlash:
17835 case Intrinsic::arm_mve_vmla_n_predicated:
17836 case Intrinsic::arm_mve_vmlas_n_predicated:
17837 case Intrinsic::arm_mve_vqdmlah_predicated:
17838 case Intrinsic::arm_mve_vqdmlash_predicated:
17839 case Intrinsic::arm_mve_vqrdmlah_predicated:
17840 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17845 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17852 case Intrinsic::arm_mve_minv:
17853 case Intrinsic::arm_mve_maxv:
17854 case Intrinsic::arm_mve_minav:
17855 case Intrinsic::arm_mve_maxav:
17856 case Intrinsic::arm_mve_minv_predicated:
17857 case Intrinsic::arm_mve_maxv_predicated:
17858 case Intrinsic::arm_mve_minav_predicated:
17859 case Intrinsic::arm_mve_maxav_predicated: {
17862 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17869 case Intrinsic::arm_mve_addv: {
17872 bool Unsigned =
N->getConstantOperandVal(2);
17873 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17877 case Intrinsic::arm_mve_addlv:
17878 case Intrinsic::arm_mve_addlv_predicated: {
17881 bool Unsigned =
N->getConstantOperandVal(2);
17882 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17883 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17884 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17887 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17889 Ops.push_back(
N->getOperand(i));
17902 EVT VT =
Y.getValueType();
17905 if (Subtarget->hasMVEIntegerOps())
17907 if (Subtarget->hasNEON())
17921 EVT VT =
N->getValueType(0);
17923 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17924 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17925 N->getOperand(0)->hasOneUse()) {
17942 if (AndMask == 255 || AndMask == 65535)
17946 if (MaskedBits > ShiftAmt) {
17961 if (ST->hasMVEIntegerOps())
17966 switch (
N->getOpcode()) {
17972 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17979 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17980 unsigned VShiftOpc =
17981 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17983 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17999 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
18002 EVT FromVT = LD->getValueType(0);
18003 EVT ToVT =
N->getValueType(0);
18010 unsigned NumElements = 0;
18011 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
18013 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
18015 if (NumElements == 0 ||
18025 SDValue BasePtr = LD->getBasePtr();
18026 Align Alignment = LD->getBaseAlign();
18047 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18048 Alignment, MMOFlags, AAInfo);
18054 if (FromEltVT == MVT::f16) {
18057 for (
unsigned i = 0; i < Loads.
size(); i++) {
18059 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
18078 EVT VT =
N->getValueType(0);
18085 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
18092 if (VT == MVT::i32 &&
18093 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
18098 switch (
N->getOpcode()) {
18101 Opc = ARMISD::VGETLANEs;
18105 Opc = ARMISD::VGETLANEu;
18112 if (ST->hasMVEIntegerOps())
18130 Ops.push_back(Ext);
18140 if (ST->hasMVEFloatOps())
18151 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
18155 EVT VT =
Op.getValueType();
18158 if (VT != MVT::i32 ||
18174 APInt MaxC = Max.getConstantOperandAPInt(1);
18175 if (MaxC.
sgt(MinC))
18182 if ((MinC + 1).isPowerOf2()) {
18204 APInt Width = MinC - MaxC + 1;
18207 unsigned SatBit = Width.
logBase2() - 1;
18225 EVT VT =
N->getValueType(0);
18228 if (VT == MVT::i32)
18231 if (!ST->hasMVEIntegerOps())
18237 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18240 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18248 if (VT == MVT::v4i32)
18249 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18251 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18258 MaxC != ~SaturateC)
18263 if (IsSignedSaturate(
N, N0.
getNode())) {
18266 if (VT == MVT::v4i32) {
18267 HalfVT = MVT::v8i16;
18268 ExtVT = MVT::v4i16;
18270 HalfVT = MVT::v16i8;
18285 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18291 if (VT == MVT::v4i32)
18292 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18294 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18303 if (IsUnsignedSaturate(
N)) {
18307 if (VT == MVT::v4i32) {
18308 HalfVT = MVT::v8i16;
18309 ExtConst = 0x0000FFFF;
18311 HalfVT = MVT::v16i8;
18333 const APInt *CV = &
C->getAPIntValue();
18390 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18397 if ((OrCI &
Known.Zero) != OrCI)
18403 EVT VT =
X.getValueType();
18404 unsigned BitInX = AndC->
logBase2();
18412 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18413 BitInY < NumActiveBits; ++BitInY) {
18414 if (OrCI[BitInY] == 0)
18417 Mask.setBit(BitInY);
18418 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18434 switch (
N->getOpcode()) {
18449 if (Const->isZero())
18451 else if (Const->isOne())
18459 unsigned IntOp =
N.getConstantOperandVal(1);
18460 if (IntOp != Intrinsic::test_start_loop_iterations &&
18461 IntOp != Intrinsic::loop_decrement_reg)
18487 bool Negate =
false;
18493 Cond =
N->getOperand(1);
18494 Dest =
N->getOperand(2);
18498 Cond =
N->getOperand(2);
18499 Dest =
N->getOperand(4);
18501 if (!Const->isOne() && !Const->isZero())
18503 Imm = Const->getZExtValue();
18531 assert((IsTrueIfZero(CC,
Imm) || IsFalseIfZero(CC,
Imm)) &&
18532 "unsupported condition");
18537 unsigned IntOp =
Int->getConstantOperandVal(1);
18538 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18539 "expected single br user");
18540 SDNode *Br = *
N->user_begin();
18550 if (IntOp == Intrinsic::test_start_loop_iterations) {
18552 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18554 if (IsTrueIfZero(CC,
Imm)) {
18556 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18560 UpdateUncondBr(Br, Dest, DAG);
18562 SDValue Ops[] = {Chain, Setup, OtherTarget};
18563 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18575 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18583 if (
Target == OtherTarget)
18584 UpdateUncondBr(Br, Dest, DAG);
18590 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18599 if (Cmp.getOpcode() != ARMISD::CMPZ)
18604 SDValue LHS = Cmp.getOperand(0);
18605 SDValue RHS = Cmp.getOperand(1);
18614 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18615 LHS->getOperand(0)->hasOneUse() &&
18619 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18631 EVT VT =
N->getValueType(0);
18632 SDValue FalseVal =
N->getOperand(0);
18633 SDValue TrueVal =
N->getOperand(1);
18641 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18648 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18651 if (Cmp.getOpcode() != ARMISD::CMPZ)
18655 SDValue LHS = Cmp.getOperand(0);
18656 SDValue RHS = Cmp.getOperand(1);
18660 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18684 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18685 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18686 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18689 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18694 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18697 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18698 LHS->getOperand(2), LHS->getOperand(3));
18708 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18712 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18714 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18723 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18756 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18768 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18788 const APInt *TrueConst;
18789 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18790 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18791 FalseVal.getOperand(1) == RHS) ||
18795 unsigned ShiftAmount = TrueConst->
logBase2();
18810 if (
Known.Zero == 0xfffffffe)
18813 else if (
Known.Zero == 0xffffff00)
18816 else if (
Known.Zero == 0xffff0000)
18829 EVT DstVT =
N->getValueType(0);
18832 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18833 EVT SrcVT = Src.getValueType();
18835 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18840 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18841 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18842 Src.getValueType().getScalarSizeInBits())
18843 Src = Src.getOperand(0);
18847 EVT SrcVT = Src.getValueType();
18848 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18849 Src.getOpcode() == ARMISD::VMVNIMM ||
18850 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18853 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18867 EVT VT =
N->getValueType(0);
18875 if (
N->getNumOperands() == 2 &&
18879 N->getOperand(0).getOperand(1),
18880 N->getOperand(1).getOperand(0),
18881 N->getOperand(1).getOperand(1));
18884 if (
N->getNumOperands() == 2 &&
18890 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18891 S0->getOperand(1) ==
S1->getOperand(1)) {
18894 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18898 ARMISD::VMOVN,
DL, VT,
18899 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18900 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18904 ARMISD::VMOVN,
DL, VT,
18905 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18906 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18914 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18915 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18916 (Op.getOpcode() == ISD::BITCAST &&
18917 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18920 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18922 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18940 int NumIns =
N->getNumOperands();
18941 assert((NumIns == 2 || NumIns == 4) &&
18942 "Expected 2 or 4 inputs to an MVETrunc");
18944 if (
N->getNumOperands() == 4)
18948 for (
int I = 0;
I < NumIns;
I++) {
18950 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18955 Ptr, MPI, StoreVT,
Align(4));
18970 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18973 EVT FromVT = LD->getMemoryVT();
18974 EVT ToVT =
N->getValueType(0);
18981 unsigned NumElements = 0;
18982 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18984 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18986 assert(NumElements != 0);
18992 LD->getExtensionType() != NewExtType)
18999 SDValue BasePtr = LD->getBasePtr();
19000 Align Alignment = LD->getBaseAlign();
19019 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
19020 Alignment, MMOFlags, AAInfo);
19036 EVT VT =
N->getValueType(0);
19038 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
19039 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
19041 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19043 auto Extend = [&](
SDValue V) {
19052 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
19053 SDValue Ext = Extend(
N->getOperand(0));
19061 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
19062 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
19066 auto CheckInregMask = [&](
int Start,
int Offset) {
19068 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
19074 if (CheckInregMask(0, 0))
19076 else if (CheckInregMask(0, 1))
19077 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19078 else if (CheckInregMask(0, Mask.size()))
19080 else if (CheckInregMask(0, Mask.size() + 1))
19081 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19086 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19090 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19097 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
19108 int NumOuts =
N->getNumValues();
19109 assert((NumOuts == 2 || NumOuts == 4) &&
19110 "Expected 2 or 4 outputs to an MVEEXT");
19111 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19113 if (
N->getNumOperands() == 4)
19119 StackPtr, MPI,
Align(4));
19122 for (
int I = 0;
I < NumOuts;
I++) {
19124 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
19125 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
19130 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
19139 switch (
N->getOpcode()) {
19199 case ARMISD::BRCOND:
19203 case ARMISD::CSINC:
19204 case ARMISD::CSINV:
19205 case ARMISD::CSNEG:
19218 case ARMISD::PREDICATE_CAST:
19220 case ARMISD::VECTOR_REG_CAST:
19231 case ARMISD::VADDVs:
19232 case ARMISD::VADDVu:
19233 case ARMISD::VADDLVs:
19234 case ARMISD::VADDLVu:
19235 case ARMISD::VADDLVAs:
19236 case ARMISD::VADDLVAu:
19237 case ARMISD::VMLAVs:
19238 case ARMISD::VMLAVu:
19239 case ARMISD::VMLALVs:
19240 case ARMISD::VMLALVu:
19241 case ARMISD::VMLALVAs:
19242 case ARMISD::VMLALVAu:
19244 case ARMISD::VMOVN:
19246 case ARMISD::VQMOVNs:
19247 case ARMISD::VQMOVNu:
19249 case ARMISD::VQDMULH:
19255 case ARMISD::SMULWB: {
19256 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19262 case ARMISD::SMULWT: {
19263 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19269 case ARMISD::SMLALBB:
19270 case ARMISD::QADD16b:
19271 case ARMISD::QSUB16b:
19272 case ARMISD::UQADD16b:
19273 case ARMISD::UQSUB16b: {
19274 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19281 case ARMISD::SMLALBT: {
19282 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19284 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19291 case ARMISD::SMLALTB: {
19292 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19294 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19301 case ARMISD::SMLALTT: {
19302 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19309 case ARMISD::QADD8b:
19310 case ARMISD::QSUB8b:
19311 case ARMISD::UQADD8b:
19312 case ARMISD::UQSUB8b: {
19313 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19321 if (
N->getOperand(1) ==
N->getOperand(2))
19322 return N->getOperand(1);
19326 switch (
N->getConstantOperandVal(1)) {
19327 case Intrinsic::arm_neon_vld1:
19328 case Intrinsic::arm_neon_vld1x2:
19329 case Intrinsic::arm_neon_vld1x3:
19330 case Intrinsic::arm_neon_vld1x4:
19331 case Intrinsic::arm_neon_vld2:
19332 case Intrinsic::arm_neon_vld3:
19333 case Intrinsic::arm_neon_vld4:
19334 case Intrinsic::arm_neon_vld2lane:
19335 case Intrinsic::arm_neon_vld3lane:
19336 case Intrinsic::arm_neon_vld4lane:
19337 case Intrinsic::arm_neon_vld2dup:
19338 case Intrinsic::arm_neon_vld3dup:
19339 case Intrinsic::arm_neon_vld4dup:
19340 case Intrinsic::arm_neon_vst1:
19341 case Intrinsic::arm_neon_vst1x2:
19342 case Intrinsic::arm_neon_vst1x3:
19343 case Intrinsic::arm_neon_vst1x4:
19344 case Intrinsic::arm_neon_vst2:
19345 case Intrinsic::arm_neon_vst3:
19346 case Intrinsic::arm_neon_vst4:
19347 case Intrinsic::arm_neon_vst2lane:
19348 case Intrinsic::arm_neon_vst3lane:
19349 case Intrinsic::arm_neon_vst4lane:
19351 case Intrinsic::arm_mve_vld2q:
19352 case Intrinsic::arm_mve_vld4q:
19353 case Intrinsic::arm_mve_vst2q:
19354 case Intrinsic::arm_mve_vst4q:
19371 unsigned *
Fast)
const {
19377 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19380 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19382 if (AllowsUnaligned) {
19384 *
Fast = Subtarget->hasV7Ops();
19389 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19393 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19400 if (!Subtarget->hasMVEIntegerOps())
19404 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19405 Ty == MVT::v2i1)) {
19413 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19429 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19430 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19431 Ty == MVT::v2f64) {
19442 const AttributeList &FuncAttributes)
const {
19444 if ((
Op.isMemcpyOrMemmove() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19445 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19447 if (
Op.size() >= 16 &&
19453 }
else if (
Op.size() >= 8 &&
19470 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19472 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19474 return (SrcBits == 64 && DestBits == 32);
19483 return (SrcBits == 64 && DestBits == 32);
19519 return Subtarget->hasFullFP16();
19526 if (!Subtarget->hasMVEIntegerOps())
19545 if (Ld->isExpandingLoad())
19549 if (Subtarget->hasMVEIntegerOps())
19562 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19594bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19596 if (Subtarget->useSoftFloat())
19605 return Subtarget->hasMVEFloatOps();
19623 unsigned Scale = 1;
19640 if ((V & (Scale - 1)) != 0)
19649 if (VT.
isVector() && Subtarget->hasNEON())
19652 !Subtarget->hasMVEFloatOps())
19655 bool IsNeg =
false;
19661 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19664 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19680 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19686 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19716 default:
return false;
19735 int Scale = AM.
Scale;
19740 default:
return false;
19748 Scale = Scale & ~1;
19749 return Scale == 2 || Scale == 4 || Scale == 8;
19766 if (Scale & 1)
return false;
19773 const int Scale = AM.
Scale;
19783 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19799 switch (AM.
Scale) {
19810 if (Subtarget->isThumb1Only())
19813 if (Subtarget->isThumb2())
19816 int Scale = AM.
Scale;
19818 default:
return false;
19822 if (Scale < 0) Scale = -Scale;
19830 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19843 if (Scale & 1)
return false;
19856 if (!Subtarget->isThumb())
19859 if (Subtarget->isThumb2())
19863 return Imm >= 0 &&
Imm <= 255;
19873 if (!Subtarget->isThumb())
19875 if (Subtarget->isThumb2())
19878 return AbsImm <= 255;
19913 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19917 int RHSC = (int)
RHS->getZExtValue();
19918 if (RHSC < 0 && RHSC > -256) {
19928 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19931 int RHSC = (int)
RHS->getZExtValue();
19932 if (RHSC < 0 && RHSC > -0x1000) {
19974 int RHSC = (int)
RHS->getZExtValue();
19975 if (RHSC < 0 && RHSC > -0x100) {
19980 }
else if (RHSC > 0 && RHSC < 0x100) {
19991 bool isSEXTLoad,
bool IsMasked,
bool isLE,
20002 bool CanChangeType = isLE && !IsMasked;
20005 int RHSC = (int)
RHS->getZExtValue();
20007 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
20008 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
20013 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
20024 if (VT == MVT::v4i16) {
20025 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
20027 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
20028 if (IsInRange(RHSC, 0x80, 1))
20030 }
else if (Alignment >= 4 &&
20031 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
20032 IsInRange(RHSC, 0x80, 4))
20034 else if (Alignment >= 2 &&
20035 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
20036 IsInRange(RHSC, 0x80, 2))
20038 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
20051 if (Subtarget->isThumb1Only())
20058 bool isSEXTLoad =
false;
20059 bool IsMasked =
false;
20061 Ptr = LD->getBasePtr();
20062 VT = LD->getMemoryVT();
20063 Alignment = LD->getAlign();
20064 AS = LD->getAddressSpace();
20067 Ptr = ST->getBasePtr();
20068 VT = ST->getMemoryVT();
20069 Alignment = ST->getAlign();
20070 AS = ST->getAddressSpace();
20072 Ptr = LD->getBasePtr();
20073 VT = LD->getMemoryVT();
20074 Alignment = LD->getAlign();
20075 AS = LD->getAddressSpace();
20079 Ptr = ST->getBasePtr();
20080 VT = ST->getMemoryVT();
20081 Alignment = ST->getAlign();
20082 AS = ST->getAddressSpace();
20097 bool isLegal =
false;
20099 isLegal = Subtarget->hasMVEIntegerOps() &&
20101 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
20102 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
20104 if (Subtarget->isThumb2())
20129 bool isSEXTLoad =
false, isNonExt;
20130 bool IsMasked =
false;
20132 VT = LD->getMemoryVT();
20133 Ptr = LD->getBasePtr();
20134 Alignment = LD->getAlign();
20138 VT = ST->getMemoryVT();
20139 Ptr = ST->getBasePtr();
20140 Alignment = ST->getAlign();
20141 isNonExt = !ST->isTruncatingStore();
20143 VT = LD->getMemoryVT();
20144 Ptr = LD->getBasePtr();
20145 Alignment = LD->getAlign();
20150 VT = ST->getMemoryVT();
20151 Ptr = ST->getBasePtr();
20152 Alignment = ST->getAlign();
20153 isNonExt = !ST->isTruncatingStore();
20158 if (Subtarget->isThumb1Only()) {
20161 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
20162 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
20165 if (!RHS || RHS->getZExtValue() != 4)
20167 if (Alignment <
Align(4))
20171 Base =
Op->getOperand(0);
20177 bool isLegal =
false;
20179 isLegal = Subtarget->hasMVEIntegerOps() &&
20184 if (Subtarget->isThumb2())
20198 !Subtarget->isThumb2())
20212 const APInt &DemandedElts,
20214 unsigned Depth)
const {
20217 switch (
Op.getOpcode()) {
20224 if (
Op.getResNo() == 0) {
20235 case ARMISD::CMOV: {
20238 if (
Known.isUnknown())
20250 case Intrinsic::arm_ldaex:
20251 case Intrinsic::arm_ldrex: {
20259 case ARMISD::BFI: {
20266 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20267 Known.Zero &= Mask;
20271 case ARMISD::VGETLANEs:
20272 case ARMISD::VGETLANEu: {
20273 const SDValue &SrcSV =
Op.getOperand(0);
20279 "VGETLANE index out of bounds");
20284 EVT VT =
Op.getValueType();
20290 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20298 case ARMISD::VMOVrh: {
20304 case ARMISD::CSINC:
20305 case ARMISD::CSINV:
20306 case ARMISD::CSNEG: {
20314 if (
Op.getOpcode() == ARMISD::CSINC)
20317 else if (
Op.getOpcode() == ARMISD::CSINV)
20319 else if (
Op.getOpcode() == ARMISD::CSNEG)
20326 case ARMISD::VORRIMM:
20327 case ARMISD::VBICIMM: {
20328 unsigned Encoded =
Op.getConstantOperandVal(1);
20329 unsigned DecEltBits = 0;
20332 unsigned EltBits =
Op.getScalarValueSizeInBits();
20333 if (EltBits != DecEltBits) {
20342 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20343 APInt Imm(DecEltBits, DecodedVal);
20354 if (!Subtarget->isThumb())
20371 if (
Imm == 0 ||
Imm == ~0U)
20374 unsigned Opc =
Op.getOpcode();
20376 EVT VT =
Op.getValueType();
20378 unsigned ShrunkImm =
Imm & Demanded;
20379 unsigned ExpandedImm =
Imm | ~Demanded;
20381 auto IsLegalImm = [ShrunkImm, ExpandedImm](
unsigned CandidateImm) ->
bool {
20382 return (ShrunkImm & CandidateImm) == ShrunkImm &&
20383 (~ExpandedImm & CandidateImm) == 0;
20385 auto UseImm = [
Imm,
Opc,
Op, VT, &TLO](
unsigned NewImm) ->
bool {
20397 if (ShrunkImm == 0) {
20398 ++NumOptimizedImms;
20399 return UseImm(ShrunkImm);
20405 if (ExpandedImm == ~0U) {
20406 ++NumOptimizedImms;
20407 return UseImm(ExpandedImm);
20415 if (IsLegalImm(0xFF)) {
20416 ++NumOptimizedImms;
20417 return UseImm(0xFF);
20420 if (IsLegalImm(0xFFFF)) {
20421 ++NumOptimizedImms;
20422 return UseImm(0xFFFF);
20436 ++NumOptimizedImms;
20437 return UseImm(ShrunkImm);
20445 if ((~ExpandedImm) < 256) {
20446 ++NumOptimizedImms;
20447 return UseImm(ExpandedImm);
20453 !Subtarget->hasV6Ops()) {
20454 ++NumOptimizedImms;
20455 return UseImm(ExpandedImm);
20474 EVT VT =
Op.getValueType();
20489 switch (
Op.getOpcode()) {
20500 unsigned Imm =
C->getZExtValue();
20507 unsigned Depth)
const {
20508 unsigned Opc =
Op.getOpcode();
20512 case ARMISD::LSRL: {
20516 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20518 unsigned ShAmt =
Op->getConstantOperandVal(2);
20528 case ARMISD::VBICIMM: {
20530 unsigned ModImm =
Op.getConstantOperandVal(1);
20531 unsigned EltBits = 0;
20533 if ((OriginalDemandedBits & Mask) == 0)
20539 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
20554 if (!Subtarget->hasVFP2Base())
20558 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20570 unsigned S = Constraint.
size();
20572 switch (Constraint[0]) {
20584 }
else if (S == 2) {
20585 switch (Constraint[0]) {
20602 Value *CallOperandVal =
info.CallOperandVal;
20605 if (!CallOperandVal)
20609 switch (*constraint) {
20615 if (Subtarget->isThumb())
20630 if (PR == 0 || VT == MVT::Other)
20632 if (ARM::SPRRegClass.
contains(PR))
20633 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20634 if (ARM::DPRRegClass.
contains(PR))
20639using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20643 switch (Constraint.
size()) {
20646 switch (Constraint[0]) {
20648 if (Subtarget->isThumb())
20649 return RCPair(0U, &ARM::tGPRRegClass);
20650 return RCPair(0U, &ARM::GPRRegClass);
20652 if (Subtarget->isThumb())
20653 return RCPair(0U, &ARM::hGPRRegClass);
20656 if (Subtarget->isThumb1Only())
20657 return RCPair(0U, &ARM::tGPRRegClass);
20658 return RCPair(0U, &ARM::GPRRegClass);
20660 if (VT == MVT::Other)
20662 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20663 return RCPair(0U, &ARM::SPRRegClass);
20665 return RCPair(0U, &ARM::DPRRegClass);
20667 return RCPair(0U, &ARM::QPRRegClass);
20670 if (VT == MVT::Other)
20672 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20673 return RCPair(0U, &ARM::SPR_8RegClass);
20675 return RCPair(0U, &ARM::DPR_8RegClass);
20677 return RCPair(0U, &ARM::QPR_8RegClass);
20680 if (VT == MVT::Other)
20682 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20683 return RCPair(0U, &ARM::SPRRegClass);
20685 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20687 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20693 if (Constraint[0] ==
'T') {
20694 switch (Constraint[1]) {
20698 return RCPair(0U, &ARM::tGPREvenRegClass);
20700 return RCPair(0U, &ARM::tGPROddRegClass);
20709 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20710 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20713 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20714 return std::make_pair(
unsigned(ARM::LR),
getRegClassFor(MVT::i32));
20718 return {0,
nullptr};
20726 std::vector<SDValue> &
Ops,
20731 if (Constraint.
size() != 1)
20734 char ConstraintLetter = Constraint[0];
20735 switch (ConstraintLetter) {
20738 case 'I':
case 'J':
case 'K':
case 'L':
20739 case 'M':
case 'N':
case 'O':
20744 int64_t CVal64 =
C->getSExtValue();
20745 int CVal = (int) CVal64;
20748 if (CVal != CVal64)
20751 switch (ConstraintLetter) {
20755 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20756 if (CVal >= 0 && CVal <= 65535)
20760 if (Subtarget->isThumb1Only()) {
20763 if (CVal >= 0 && CVal <= 255)
20765 }
else if (Subtarget->isThumb2()) {
20779 if (Subtarget->isThumb1Only()) {
20784 if (CVal >= -255 && CVal <= -1)
20790 if (CVal >= -4095 && CVal <= 4095)
20796 if (Subtarget->isThumb1Only()) {
20803 }
else if (Subtarget->isThumb2()) {
20823 if (Subtarget->isThumb1Only()) {
20826 if (CVal >= -7 && CVal < 7)
20828 }
else if (Subtarget->isThumb2()) {
20848 if (Subtarget->isThumb1Only()) {
20851 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20857 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20863 if (Subtarget->isThumb1Only()) {
20865 if (CVal >= 0 && CVal <= 31)
20871 if (Subtarget->isThumb1Only()) {
20874 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20883 if (Result.getNode()) {
20884 Ops.push_back(Result);
20894 "Unhandled Opcode in getDivRemLibcall");
20900 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20901 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20902 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20903 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20912 "Unhandled Opcode in getDivRemArgList");
20916 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20917 EVT ArgVT =
N->getOperand(i).getValueType();
20922 Args.push_back(Entry);
20930 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20931 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20932 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20933 "Register-based DivRem lowering only");
20934 unsigned Opcode =
Op->getOpcode();
20936 "Invalid opcode for Div/Rem lowering");
20938 EVT VT =
Op->getValueType(0);
20960 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20961 : Subtarget->hasDivideInARMMode();
20962 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20963 Op->getSimpleValueType(0) == MVT::i32) {
20965 const SDValue Dividend =
Op->getOperand(0);
20966 const SDValue Divisor =
Op->getOperand(1);
20967 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20990 if (
getTM().getTargetTriple().isOSWindows())
20993 TargetLowering::CallLoweringInfo CLI(DAG);
20997 Callee, std::move(Args))
21002 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
21003 return CallInfo.first;
21009 EVT VT =
N->getValueType(0);
21015 Result[0], Result[1]);
21019 std::vector<Type*> RetTyParams;
21020 Type *RetTyElement;
21030 RetTyParams.push_back(RetTyElement);
21031 RetTyParams.push_back(RetTyElement);
21046 if (
getTM().getTargetTriple().isOSWindows())
21053 Callee, std::move(Args))
21057 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
21060 SDNode *ResNode = CallResult.first.getNode();
21067 assert(
getTM().getTargetTriple().isOSWindows() &&
21068 "unsupported target platform");
21076 "no-stack-arg-probe")) {
21080 Chain =
SP.getValue(1);
21097 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
21098 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
21108 bool IsStrict =
Op->isStrictFPOpcode();
21109 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21110 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21112 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
21113 "Unexpected type for custom-lowering FP_EXTEND");
21115 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21116 "With both FP DP and 16, any FP conversion is legal!");
21118 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
21119 "With FP16, 16 to 32 conversion is legal!");
21122 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
21127 Loc,
Op.getValueType(), SrcVal);
21142 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
21143 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
21144 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
21145 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
21149 {DstVT, MVT::Other}, {Chain, SrcVal});
21156 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21157 "Unexpected type for custom-lowering FP_EXTEND");
21158 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21163 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
21167 bool IsStrict =
Op->isStrictFPOpcode();
21169 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21171 EVT DstVT =
Op.getValueType();
21173 if (DstVT == MVT::bf16) {
21174 if (Subtarget->hasBF16() && SrcVT == MVT::f32)
21179 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21182 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
21183 "Unexpected type for custom-lowering FP_ROUND");
21185 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21186 "With both FP DP and 16, any FP conversion is legal!");
21191 if (SrcSz == 32 && Subtarget->hasFP16())
21196 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21197 "Unexpected type for custom-lowering FP_ROUND");
21201 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21213 if (v == 0xffffffff)
21225 bool ForCodeSize)
const {
21226 if (!Subtarget->hasVFP3Base())
21228 if (VT == MVT::f16 && Subtarget->hasFullFP16())
21230 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
21233 if (VT == MVT::f32)
21235 if (VT == MVT::f64 && Subtarget->hasFP64())
21248 case Intrinsic::arm_neon_vld1:
21249 case Intrinsic::arm_neon_vld2:
21250 case Intrinsic::arm_neon_vld3:
21251 case Intrinsic::arm_neon_vld4:
21252 case Intrinsic::arm_neon_vld2lane:
21253 case Intrinsic::arm_neon_vld3lane:
21254 case Intrinsic::arm_neon_vld4lane:
21255 case Intrinsic::arm_neon_vld2dup:
21256 case Intrinsic::arm_neon_vld3dup:
21257 case Intrinsic::arm_neon_vld4dup: {
21260 auto &
DL =
I.getDataLayout();
21261 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21263 Info.ptrVal =
I.getArgOperand(0);
21265 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21272 case Intrinsic::arm_neon_vld1x2:
21273 case Intrinsic::arm_neon_vld1x3:
21274 case Intrinsic::arm_neon_vld1x4: {
21277 auto &
DL =
I.getDataLayout();
21278 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21280 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
21282 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
21288 case Intrinsic::arm_neon_vst1:
21289 case Intrinsic::arm_neon_vst2:
21290 case Intrinsic::arm_neon_vst3:
21291 case Intrinsic::arm_neon_vst4:
21292 case Intrinsic::arm_neon_vst2lane:
21293 case Intrinsic::arm_neon_vst3lane:
21294 case Intrinsic::arm_neon_vst4lane: {
21297 auto &
DL =
I.getDataLayout();
21298 unsigned NumElts = 0;
21299 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21300 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21303 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21306 Info.ptrVal =
I.getArgOperand(0);
21308 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21315 case Intrinsic::arm_neon_vst1x2:
21316 case Intrinsic::arm_neon_vst1x3:
21317 case Intrinsic::arm_neon_vst1x4: {
21320 auto &
DL =
I.getDataLayout();
21321 unsigned NumElts = 0;
21322 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21323 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21326 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21329 Info.ptrVal =
I.getArgOperand(0);
21331 Info.align =
I.getParamAlign(0).valueOrOne();
21337 case Intrinsic::arm_mve_vld2q:
21338 case Intrinsic::arm_mve_vld4q: {
21342 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21344 Info.ptrVal =
I.getArgOperand(0);
21352 case Intrinsic::arm_mve_vst2q:
21353 case Intrinsic::arm_mve_vst4q: {
21356 Type *VecTy =
I.getArgOperand(1)->getType();
21357 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21359 Info.ptrVal =
I.getArgOperand(0);
21367 case Intrinsic::arm_mve_vldr_gather_base:
21368 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21370 Info.ptrVal =
nullptr;
21372 Info.align =
Align(1);
21377 case Intrinsic::arm_mve_vldr_gather_base_wb:
21378 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21380 Info.ptrVal =
nullptr;
21381 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21382 Info.align =
Align(1);
21387 case Intrinsic::arm_mve_vldr_gather_offset:
21388 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21390 Info.ptrVal =
nullptr;
21395 Info.align =
Align(1);
21400 case Intrinsic::arm_mve_vstr_scatter_base:
21401 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21403 Info.ptrVal =
nullptr;
21404 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21405 Info.align =
Align(1);
21410 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21411 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21413 Info.ptrVal =
nullptr;
21414 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21415 Info.align =
Align(1);
21420 case Intrinsic::arm_mve_vstr_scatter_offset:
21421 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21423 Info.ptrVal =
nullptr;
21428 Info.align =
Align(1);
21433 case Intrinsic::arm_ldaex:
21434 case Intrinsic::arm_ldrex: {
21435 auto &
DL =
I.getDataLayout();
21436 Type *ValTy =
I.getParamElementType(0);
21439 Info.ptrVal =
I.getArgOperand(0);
21441 Info.align =
DL.getABITypeAlign(ValTy);
21446 case Intrinsic::arm_stlex:
21447 case Intrinsic::arm_strex: {
21448 auto &
DL =
I.getDataLayout();
21449 Type *ValTy =
I.getParamElementType(1);
21452 Info.ptrVal =
I.getArgOperand(1);
21454 Info.align =
DL.getABITypeAlign(ValTy);
21459 case Intrinsic::arm_stlexd:
21460 case Intrinsic::arm_strexd:
21462 Info.memVT = MVT::i64;
21463 Info.ptrVal =
I.getArgOperand(2);
21465 Info.align =
Align(8);
21470 case Intrinsic::arm_ldaexd:
21471 case Intrinsic::arm_ldrexd:
21473 Info.memVT = MVT::i64;
21474 Info.ptrVal =
I.getArgOperand(0);
21476 Info.align =
Align(8);
21490 assert(Ty->isIntegerTy());
21492 unsigned Bits = Ty->getPrimitiveSizeInBits();
21493 if (Bits == 0 || Bits > 32)
21500 unsigned Index)
const {
21512 if (!Subtarget->hasDataBarrier()) {
21516 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21517 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21518 Builder.getInt32(0), Builder.getInt32(7),
21519 Builder.getInt32(10), Builder.getInt32(5)};
21520 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_mcr,
args);
21529 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_dmb, CDomain);
21550 if (Subtarget->preferISHSTBarriers())
21583 bool has64BitAtomicStore;
21584 if (Subtarget->isMClass())
21585 has64BitAtomicStore =
false;
21586 else if (Subtarget->isThumb())
21587 has64BitAtomicStore = Subtarget->hasV7Ops();
21589 has64BitAtomicStore = Subtarget->hasV6Ops();
21591 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21605 bool has64BitAtomicLoad;
21606 if (Subtarget->isMClass())
21607 has64BitAtomicLoad =
false;
21608 else if (Subtarget->isThumb())
21609 has64BitAtomicLoad = Subtarget->hasV7Ops();
21611 has64BitAtomicLoad = Subtarget->hasV6Ops();
21627 if (Subtarget->isMClass())
21628 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21629 else if (Subtarget->isThumb())
21630 hasAtomicRMW = Subtarget->hasV7Ops();
21632 hasAtomicRMW = Subtarget->hasV6Ops();
21633 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21657 bool HasAtomicCmpXchg;
21658 if (Subtarget->isMClass())
21659 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21660 else if (Subtarget->isThumb())
21661 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21663 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21665 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21672 return InsertFencesForAtomic;
21677 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21683 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21684 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21686 RTLIB::LibcallImpl SecurityCookieVar =
21687 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21688 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21689 SecurityCookieVar != RTLIB::Unsupported) {
21700 F->addParamAttr(0, Attribute::AttrKind::InReg);
21707 unsigned &
Cost)
const {
21709 if (!Subtarget->hasNEON())
21738 unsigned Opcode =
Op.getOpcode();
21740 case ARMISD::VORRIMM:
21741 case ARMISD::VBICIMM:
21745 Op, DemandedElts, DAG, Kind, ConsiderFlags,
Depth);
21749 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21753 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21758 if (!Subtarget->hasV7Ops())
21764 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21766 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21774 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21783 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21789 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21791 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21794 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21796 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21797 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21798 if (!Subtarget->isLittle())
21800 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21801 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21802 return Builder.CreateOr(
21803 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21807 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21808 CallInst *CI = Builder.CreateIntrinsicWithoutFolding(
Int, Tys, Addr);
21811 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21812 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21817 if (!Subtarget->hasV7Ops())
21819 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21825 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21833 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21836 Value *
Lo = Builder.CreateTrunc(Val, Int32Ty,
"lo");
21837 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32), Int32Ty,
"hi");
21838 if (!Subtarget->isLittle())
21840 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21843 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21847 CallInst *CI = Builder.CreateCall(
21848 Strex, {Builder.CreateZExtOrBitCast(
21858 return Subtarget->isMClass();
21866 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21873 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21876 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21884 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21892 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21895 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21900 if (Subtarget->hasNEON() && VecSize == 64)
21902 return VecSize % 128 == 0;
21906 if (Subtarget->hasNEON())
21908 if (Subtarget->hasMVEIntegerOps())
21928 "Invalid interleave factor");
21929 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21931 "Unmatched number of shufflevectors and indices");
21936 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21939 Type *EltTy = VecTy->getElementType();
21942 Align Alignment = LI->getAlign();
21960 Value *BaseAddr = LI->getPointerOperand();
21962 if (NumLoads > 1) {
21966 VecTy->getNumElements() / NumLoads);
21972 if (Subtarget->hasNEON()) {
21973 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21974 Type *Tys[] = {VecTy, PtrTy};
21975 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21976 Intrinsic::arm_neon_vld3,
21977 Intrinsic::arm_neon_vld4};
21980 Ops.push_back(BaseAddr);
21981 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21983 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21986 assert((Factor == 2 || Factor == 4) &&
21987 "expected interleave factor of 2 or 4 for MVE");
21989 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21990 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21991 Type *Tys[] = {VecTy, PtrTy};
21994 Ops.push_back(BaseAddr);
21995 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
22005 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
22009 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
22010 VecTy->getNumElements() * Factor);
22016 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
22018 unsigned Index = Indices[i];
22020 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
22024 SubVec = Builder.CreateIntToPtr(
22028 SubVecs[SV].push_back(SubVec);
22037 auto &SubVec = SubVecs[SVI];
22040 SVI->replaceAllUsesWith(WideVec);
22076 const APInt &GapMask)
const {
22078 "Invalid interleave factor");
22083 "Unexpected mask on store");
22086 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
22088 unsigned LaneLen = VecTy->getNumElements() / Factor;
22089 Type *EltTy = VecTy->getElementType();
22093 Align Alignment =
SI->getAlign();
22110 Type *IntTy =
DL.getIntPtrType(EltTy);
22115 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
22116 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
22122 Value *BaseAddr =
SI->getPointerOperand();
22124 if (NumStores > 1) {
22127 LaneLen /= NumStores;
22137 if (Subtarget->hasNEON()) {
22138 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
22139 Intrinsic::arm_neon_vst3,
22140 Intrinsic::arm_neon_vst4};
22141 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22142 Type *Tys[] = {PtrTy, SubVecTy};
22145 Ops.push_back(BaseAddr);
22147 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
22148 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
22150 assert((Factor == 2 || Factor == 4) &&
22151 "expected interleave factor of 2 or 4 for MVE");
22153 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
22154 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22155 Type *Tys[] = {PtrTy, SubVecTy};
22158 Ops.push_back(BaseAddr);
22160 for (
unsigned F = 0;
F < Factor;
F++) {
22161 Ops.push_back(Builder.getInt32(
F));
22162 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
22168 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
22171 if (StoreCount > 0)
22172 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
22173 BaseAddr, LaneLen * Factor);
22178 for (
unsigned i = 0; i < Factor; i++) {
22179 unsigned IdxI = StoreCount * LaneLen * Factor + i;
22180 if (Mask[IdxI] >= 0) {
22181 Shuffles.
push_back(Builder.CreateShuffleVector(
22184 unsigned StartMask = 0;
22185 for (
unsigned j = 1; j < LaneLen; j++) {
22186 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
22187 if (Mask[IdxJ * Factor + IdxI] >= 0) {
22188 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
22198 Shuffles.
push_back(Builder.CreateShuffleVector(
22219 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
22223 Members += SubMembers;
22229 Members += SubMembers * AT->getNumElements();
22230 }
else if (Ty->isFloatTy()) {
22235 }
else if (Ty->isDoubleTy()) {
22247 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
22249 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
22251 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
22264 return (Members > 0 && Members <= 4);
22270 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
22272 return ABITypeAlign;
22277 assert(StackAlign &&
"data layout string is missing stack alignment");
22278 return std::min(ABITypeAlign, *StackAlign);
22292 uint64_t Members = 0;
22296 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
22297 return IsHA || IsIntArray;
22320void ARMTargetLowering::insertCopiesSplitCSR(
22324 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22334 RC = &ARM::GPRRegClass;
22335 else if (ARM::DPRRegClass.
contains(*
I))
22336 RC = &ARM::DPRRegClass;
22346 assert(Entry->getParent()->getFunction().hasFnAttribute(
22347 Attribute::NoUnwind) &&
22348 "Function should be nounwind in insertCopiesSplitCSR!");
22349 Entry->addLiveIn(*
I);
22354 for (
auto *Exit : Exits)
22356 TII->get(TargetOpcode::COPY), *
I)
22367 return Subtarget->hasMVEIntegerOps();
22377 unsigned NumElements = VTy->getNumElements();
22384 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22385 return Subtarget->hasMVEFloatOps();
22390 return Subtarget->hasMVEIntegerOps() &&
22391 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22392 ScalarTy->isIntegerTy(32));
22396 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22407 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22409 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22411 if (TyWidth > 128) {
22412 int Stride = Ty->getNumElements() / 2;
22416 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22418 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22419 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22420 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22421 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22422 Value *LowerSplitAcc =
nullptr;
22423 Value *UpperSplitAcc =
nullptr;
22426 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22427 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22431 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22433 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22435 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22436 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22443 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22446 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22448 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22449 {ConstRotation, InputB, InputA});
22454 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22457 ConstRotation = ConstantInt::get(IntTy, 0);
22459 ConstRotation = ConstantInt::get(IntTy, 1);
22461 if (!ConstRotation)
22464 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22465 {ConstHalving, ConstRotation, InputA, InputB});
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 SDValue carryFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG, bool Invert)
static SDValue overflowFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue valueToCarryFlag(SDValue Value, SelectionDAG &DAG, bool Invert)
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 unsigned getCmpOperandFoldingProfit(SDValue Op, bool AllowExtend)
Returns how profitable it is to fold a comparison's operand's shift and/or extension operations.
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 bool optimizeLogicalImm(SDValue Op, unsigned Size, uint64_t Imm, const APInt &Demanded, TargetLowering::TargetLoweringOpt &TLO, unsigned NewOpc)
static bool isSafeSignedCMN(SDValue Op, SelectionDAG &DAG)
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 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 LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static SDValue matchCSET(unsigned &Opcode, bool &InvertCond, SDValue TrueVal, SDValue FalseVal, const ARMSubtarget *Subtarget)
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 void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getInvertedARMCondCode(SDValue ARMcc, SelectionDAG &DAG)
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 SDValue LowerADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG, unsigned Opcode, bool IsSigned)
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 int getNegationCost(SDValue Op)
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 bool isLegalLogicalImmediate(unsigned Imm, const ARMSubtarget *Subtarget)
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 LowerTruncate(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformHWLoopCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformORCombineToShiftInsert(SelectionDAG &DAG, SDValue AndOp, SDValue ShiftOp, EVT VT, SDLoc dl)
static SDValue PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static constexpr roundingMode rmTowardZero
LLVM_ABI 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.
bool isOne() const
Determine if this is a value of 1.
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.
const ARMBaseRegisterInfo & getRegisterInfo() const
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, ARMCP::ARMCPModifier Modifier=ARMCP::no_modifier, bool AddCurrentAddress=false)
ARMConstantPoolValue - ARM specific constantpool value.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
int getVarArgsFrameIndex() const
int getPromotedConstpoolIncrease() const
SmallPtrSet< const GlobalVariable *, 2 > & getGlobalsPromotedToConstantPool()
void setArgumentStackToRestore(unsigned v)
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
void setPromotedConstpoolIncrease(int Sz)
bool isThumb1OnlyFunction() const
void setArgRegsSaveSize(unsigned s)
bool isCmseNSEntryFunction() const
void setReturnRegsCount(unsigned s)
void setVarArgsFrameIndex(int Index)
unsigned getArgRegsSaveSize() const
void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV)
Indicate to the backend that GV has had its storage changed to inside a constant pool.
void setIsSplitCSR(bool s)
void setArgumentStackSize(unsigned size)
unsigned getArgumentStackSize() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
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,...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
bool shouldFoldConstantShiftPairToMask(const SDNode *N) const override
Return true if it is profitable to fold a pair of shifts into a mask.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override
Return true if it is profitable to combine an XOR of a logical shift to create a logical shift of NOT...
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const
PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
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
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const override
Inserts necessary declarations for SSP (stack protection) purpose.
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
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
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...
Register getExceptionPointerRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
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 preferSelectsOverBooleanArithmetic(EVT VT) const override
Should we prefer selects to doing arithmetic on boolean types.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
Register getExceptionSelectorRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of EXTRACT_SUBVECTOR for this result type with this index.
CallingConv::ID getEffectiveCallingConv(CallingConv::ID CC, bool isVarArg) const
getEffectiveCallingConv - Get the effective calling convention, taking into account presence of float...
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
bool supportKCFIBundles() const override
Return true if the target supports kcfi operand bundles.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
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...
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.
bool hasAndNotCompare(SDValue V) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
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.
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.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
bool isFloatingPointOperation() const
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
The address of a basic block.
static constexpr 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.
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
const APFloat & getValueAPF() const
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
MachineConstantPoolValue * getMachineCPVal() const
bool isMachineConstantPoolEntry() const
const Constant * getConstVal() const
LLVM_ABI Type * getType() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
MaybeAlign getStackAlignment() const
Returns the natural stack alignment, or MaybeAlign() if one wasn't specified.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
StringRef getInternalSymbolPrefix() const
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
Tracks which library functions to use for a particular subtarget or function.
CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const
Get the CallingConv that should be used for the specified libcall.
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Describe properties that are true of each instruction in the target description file.
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
bool is64BitVector() const
Return true if this is a 64-bit vector type.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
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...
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI unsigned createJumpTableIndex(const std::vector< MachineBasicBlock * > &DestBBs)
createJumpTableIndex - Create a new jump table.
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
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 the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
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()
SDNodeFlags getFlags() const
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
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...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
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 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 getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
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)
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
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 void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
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 MMOMetadata &Metadata=MMOMetadata())
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 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 SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
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
const LibcallLoweringInfo & getLibcalls() 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.
LLVM_ABI OverflowKind computeOverflowForSignedAdd(SDValue N0, SDValue N1) const
Determine if the result of the signed addition of 2 nodes can overflow.
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
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
This instruction constructs a fixed permutation of two input vectors.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
Represent a constant reference to a string, i.e.
const unsigned char * bytes_end() const
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
const unsigned char * bytes_begin() const
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
Provides information about what library functions are available for the current target.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
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
virtual void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const
Inserts necessary declarations for SSP (stack protection) purpose.
void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked load does or does not work with the specified type and ind...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
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...
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
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...
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 ...
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.
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.
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
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...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
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 an n/2-bit algorithm.
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual ArrayRef< MCPhysReg > getRoundingControlRegisters() const
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
void setTypeIdForCallsiteInfo(const CallBase *CB, MachineFunction &MF, MachineFunction::CallSiteInfo &CSInfo) const
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.
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.
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.
bool isOSWindows() const
Tests whether the OS is Windows.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
Base class of all SIMD vector types.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static CondCodes getOppositeCondition(CondCodes CC)
static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC)
getSwappedCondition - assume the flags are set by MI(a,b), return the condition code if we modify the...
@ SECREL
Thread Pointer Offset.
@ GOT_PREL
Thread Local Storage (General Dynamic Mode)
@ 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
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
const unsigned FPReservedBits
const unsigned RoundingBitsPos
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.
@ POISON
POISON - A poison node.
@ 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.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ 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).
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ 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.
@ 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,...
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ 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.
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ 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],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ 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...
@ SADDO_CARRY
Carry-using overflow-aware nodes for multiple precision addition and subtraction.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
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.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
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.
RelativeUniformCounterPtr Values
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
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...
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
const unsigned PerfectShuffleTable[6561+1]
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.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
@ SjLj
setjmp/longjmp based exceptions
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.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
UndefPoisonKind
Enumeration to track whether we are interested in Undef, Poison, or both.
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)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element 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.
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.
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.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)