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 (!
getTM().isAAPCS_ABI())
1711 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1712 Subtarget->isTargetHardFloat() && !isVarArg)
1718 if (!
getTM().isAAPCS_ABI()) {
1719 if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() && !isVarArg)
1722 }
else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1731 bool isVarArg)
const {
1732 return CCAssignFnForNode(CC,
false, isVarArg);
1736 bool isVarArg)
const {
1737 return CCAssignFnForNode(CC,
true, isVarArg);
1744 bool isVarArg)
const {
1745 switch (getEffectiveCallingConv(CC, isVarArg)) {
1771 if (Subtarget->hasFullFP16()) {
1772 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1784 if (Subtarget->hasFullFP16()) {
1785 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1798SDValue ARMTargetLowering::LowerCallResult(
1802 SDValue ThisVal,
bool isCmseNSCall)
const {
1810 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1811 CCValAssign VA = RVLocs[i];
1815 if (i == 0 && isThisReturn) {
1817 "unexpected return calling convention register assignment");
1835 if (!Subtarget->isLittle())
1837 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1852 if (!Subtarget->isLittle())
1854 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1884 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1895std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1897 bool IsTailCall,
int SPDiff)
const {
1899 MachinePointerInfo DstInfo;
1919 return std::make_pair(DstAddr, DstInfo);
1928ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1941 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1944 int SrcFI = SrcFrameIdxNode->getIndex();
1945 int DstFI = DstFrameIdxNode->getIndex();
1947 "byval passed in non-fixed stack slot");
1969 if (SrcOffset == DstOffset)
1977 RegsToPassVector &RegsToPass,
1984 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1985 unsigned id = Subtarget->isLittle() ? 0 : 1;
1997 MachinePointerInfo DstInfo;
1998 std::tie(DstAddr, DstInfo) =
1999 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2016 SelectionDAG &DAG = CLI.
DAG;
2018 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2019 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2020 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2027 const CallBase *CB = CLI.
CB;
2030 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2032 MachineFunction::CallSiteInfo CSInfo;
2033 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2034 bool isThisReturn =
false;
2035 bool isCmseNSCall =
false;
2036 bool isSibCall =
false;
2037 bool PreferIndirect =
false;
2038 bool GuardWithBTI =
false;
2048 !Subtarget->noBTIAtReturnTwice())
2056 isCmseNSCall =
true;
2059 if (!Subtarget->supportsTailCall())
2075 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2076 count_if(GV->users(), [&BB](
const User *U) {
2077 return isa<Instruction>(U) &&
2078 cast<Instruction>(U)->getParent() == BB;
2085 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2099 "site marked musttail");
2102 unsigned NumBytes = CCInfo.getStackSize();
2111 if (isTailCall && !isSibCall) {
2112 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2113 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2118 assert(StackAlign &&
"data layout string is missing stack alignment");
2119 NumBytes =
alignTo(NumBytes, *StackAlign);
2124 SPDiff = NumReusableBytes - NumBytes;
2128 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2144 RegsToPassVector RegsToPass;
2153 DenseMap<unsigned, SDValue> ByValTemporaries;
2157 for (
const CCValAssign &VA : ArgLocs) {
2159 SDValue Src = OutVals[ArgIdx];
2160 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2162 if (!
Flags.isByVal())
2166 MachinePointerInfo DstInfo;
2167 std::tie(Dst, DstInfo) =
2168 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2169 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2171 if (Copy == NoCopy) {
2176 }
else if (Copy == CopyOnce) {
2180 ByValTemporaries[ArgIdx] = Src;
2182 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2186 int TempFrameIdx = MFI.CreateStackObject(
2187 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2195 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2196 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2198 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2199 ByValTemporaries[ArgIdx] = Temp;
2202 if (!ByValCopyChains.
empty())
2212 bool AfterFormalArgLoads =
false;
2216 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2218 ++i, ++realArgIdx) {
2219 CCValAssign &VA = ArgLocs[i];
2220 SDValue Arg = OutVals[realArgIdx];
2221 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2222 bool isByVal =
Flags.isByVal();
2242 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2244 if (ByValTempChain) {
2249 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2250 if (Outs[
I].
Flags.isByVal())
2258 FrameIndexSDNode *FIN =
2263 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2266 for (
const CCValAssign &VA : ArgLocs) {
2274 if (!IncomingLoad.
empty()) {
2282 AfterFormalArgLoads =
true;
2294 auto ArgVT = Outs[realArgIdx].ArgVT;
2295 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2313 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2314 StackPtr, MemOpChains, isTailCall, SPDiff);
2318 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2319 StackPtr, MemOpChains, isTailCall, SPDiff);
2323 MachinePointerInfo DstInfo;
2324 std::tie(DstAddr, DstInfo) =
2325 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2329 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2330 StackPtr, MemOpChains, isTailCall, SPDiff);
2332 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2333 Outs[0].VT == MVT::i32) {
2335 "unexpected calling convention register assignment");
2337 "unexpected use of 'returned'");
2338 isThisReturn =
true;
2343 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2344 }
else if (isByVal) {
2346 unsigned offset = 0;
2350 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2351 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2354 bool NeedsStackCopy;
2355 if (
auto It = ByValTemporaries.
find(realArgIdx);
2356 It != ByValTemporaries.
end()) {
2357 ByValSrc = It->second;
2358 NeedsStackCopy =
true;
2361 NeedsStackCopy = !isTailCall;
2365 if (CurByValIdx < ByValArgsCount) {
2366 unsigned RegBegin, RegEnd;
2367 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2371 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2375 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2378 RegsToPass.push_back(std::make_pair(j,
Load));
2383 offset = RegEnd - RegBegin;
2385 CCInfo.nextInRegsParam();
2390 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2393 MachinePointerInfo DstInfo;
2394 std::tie(Dst, DstInfo) =
2395 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2403 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2404 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2411 MachinePointerInfo DstInfo;
2412 std::tie(DstAddr, DstInfo) =
2413 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2420 if (!MemOpChains.
empty())
2426 for (
const auto &[
Reg,
N] : RegsToPass) {
2434 bool isDirect =
false;
2437 const Triple &
TT = TM.getTargetTriple();
2438 const GlobalValue *GVal =
nullptr;
2440 GVal =
G->getGlobal();
2441 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2443 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2444 bool isLocalARMFunc =
false;
2447 if (Subtarget->genLongCalls()) {
2449 if (isPIC && Subtarget->genExecuteOnly())
2451 "position-independent code is not supported");
2452 if (Subtarget->isROPI())
2459 if (Subtarget->genExecuteOnly()) {
2462 if (Subtarget->useMovt())
2485 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2491 const char *Sym = S->getSymbol();
2493 if (Subtarget->genExecuteOnly()) {
2496 if (Subtarget->useMovt())
2503 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
2509 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2514 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, GOTOffset, PICLabel);
2526 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2533 if (!PreferIndirect) {
2538 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2540 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2541 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2543 ARMISD::WrapperPIC, dl, PtrVt,
2550 }
else if (Subtarget->isTargetCOFF()) {
2551 assert(Subtarget->isTargetWindows() &&
2552 "Windows is the only supported COFF target");
2556 else if (!TM.shouldAssumeDSOLocal(GVal))
2563 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2572 const char *Sym = S->getSymbol();
2573 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2575 ARMConstantPoolValue *CPV =
2577 ARMPCLabelIndex, 4);
2579 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2584 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2591 assert(!isARMFunc && !isDirect &&
2592 "Cannot handle call to ARM function or direct call");
2596 "call to non-secure function would require "
2597 "passing arguments on stack",
2603 "call to non-secure function would return value through pointer",
2610 if (Subtarget->isThumb()) {
2612 CallOpc = ARMISD::t2CALL_BTI;
2613 else if (isCmseNSCall)
2614 CallOpc = ARMISD::tSECALL;
2615 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2616 CallOpc = ARMISD::CALL_NOLINK;
2618 CallOpc = ARMISD::CALL;
2620 if (!isDirect && !Subtarget->hasV5TOps())
2621 CallOpc = ARMISD::CALL_NOLINK;
2622 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2624 !Subtarget->hasMinSize())
2626 CallOpc = ARMISD::CALL_NOLINK;
2628 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2635 if (isTailCall && !isSibCall) {
2640 std::vector<SDValue>
Ops;
2641 Ops.push_back(Chain);
2642 Ops.push_back(Callee);
2650 for (
const auto &[
Reg,
N] : RegsToPass)
2654 const uint32_t *
Mask;
2655 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2663 isThisReturn =
false;
2669 assert(Mask &&
"Missing call preserved mask for calling convention");
2673 Ops.push_back(InGlue);
2686 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2697 uint64_t CalleePopBytes =
2700 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2706 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2707 InVals, isThisReturn,
2708 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2715void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2716 Align Alignment)
const {
2718 Alignment = std::max(Alignment,
Align(4));
2724 unsigned AlignInRegs = Alignment.
value() / 4;
2725 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2726 for (
unsigned i = 0; i < Waste; ++i)
2732 unsigned Excess = 4 * (ARM::R4 -
Reg);
2739 if (NSAAOffset != 0 &&
Size > Excess) {
2751 unsigned ByValRegBegin =
Reg;
2752 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2756 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2762 Size = std::max<int>(
Size - Excess, 0);
2770bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2776 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2777 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2778 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2779 const SelectionDAG &DAG = CLI.
DAG;
2784 assert(Subtarget->supportsTailCall());
2797 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2799 if (!(Subtarget->isThumb1Only() ||
2800 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2801 AddressRegisters.
insert(ARM::R12);
2802 for (
const CCValAssign &AL : ArgLocs)
2804 AddressRegisters.
erase(
AL.getLocReg());
2805 if (AddressRegisters.
empty()) {
2806 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2825 <<
" (guaranteed tail-call CC)\n");
2826 return CalleeCC == CallerCC;
2831 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2833 if (isCalleeStructRet != isCallerStructRet) {
2846 const GlobalValue *GV =
G->getGlobal();
2849 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2850 TT.isOSBinFormatMachO())) {
2859 getEffectiveCallingConv(CalleeCC, isVarArg),
2860 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
2867 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2868 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2869 if (CalleeCC != CallerCC) {
2870 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2871 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2880 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2888 const MachineRegisterInfo &MRI = MF.
getRegInfo();
2890 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2909 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2918 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2931 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2934 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2938 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2943 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2965 bool isLittleEndian = Subtarget->isLittle();
2968 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2977 "secure entry function would return value through pointer",
2982 for (
unsigned i = 0, realRVLocIdx = 0;
2984 ++i, ++realRVLocIdx) {
2985 CCValAssign &VA = RVLocs[i];
2988 SDValue Arg = OutVals[realRVLocIdx];
2989 bool ReturnF16 =
false;
2991 if (Subtarget->hasFullFP16() && Subtarget->isTargetHardFloat()) {
3024 auto RetVT = Outs[realRVLocIdx].ArgVT;
3046 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3050 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3056 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3068 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3070 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3075 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3085 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3111 !Subtarget->isMClass()) {
3112 if (Subtarget->isThumb1Only())
3119 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3122bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3123 if (
N->getNumValues() != 1)
3125 if (!
N->hasNUsesOfValue(1, 0))
3129 SDNode *
Copy = *
N->user_begin();
3133 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3135 TCChain =
Copy->getOperand(0);
3136 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3137 SDNode *VMov =
Copy;
3139 SmallPtrSet<SDNode*, 2>
Copies;
3140 for (SDNode *U : VMov->
users()) {
3148 for (SDNode *U : VMov->
users()) {
3149 SDValue UseChain =
U->getOperand(0);
3157 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3165 if (!
Copy->hasOneUse())
3172 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3174 TCChain =
Copy->getOperand(0);
3179 bool HasRet =
false;
3180 for (
const SDNode *U :
Copy->users()) {
3181 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3182 U->getOpcode() != ARMISD::INTRET_GLUE)
3194bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3195 if (!Subtarget->supportsTailCall())
3212 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3228 EVT PtrVT =
Op.getValueType();
3238 if (Subtarget->genExecuteOnly()) {
3243 auto GV =
new GlobalVariable(
3249 return LowerGlobalAddress(GA, DAG);
3255 if (Subtarget->isThumb1Only())
3256 CPAlign = std::max(CPAlign,
Align(4));
3262 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3269 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3278 unsigned ARMPCLabelIndex = 0;
3284 if (!IsPositionIndependent) {
3287 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3294 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3298 if (!IsPositionIndependent)
3301 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3329ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3332 "This function expects a Darwin target");
3337 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3343 MVT::i32,
DL, Chain, DescAddr,
3358 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3367 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3373ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3376 "Windows specific TLS lowering");
3400 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3408 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3409 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3415 MachinePointerInfo());
3422 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3435 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3437 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3439 ARMConstantPoolValue *CPV =
3450 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3457 TargetLowering::CallLoweringInfo CLI(DAG);
3462 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3463 return CallResult.first;
3472 const GlobalValue *GV = GA->
getGlobal();
3478 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3482 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3485 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3486 ARMConstantPoolValue *CPV =
3493 PtrVT, dl, Chain,
Offset,
3501 PtrVT, dl, Chain,
Offset,
3506 ARMConstantPoolValue *CPV =
3511 PtrVT, dl, Chain,
Offset,
3527 if (
TT.isOSDarwin())
3528 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3530 if (
TT.isOSWindows())
3531 return LowerGlobalTLSAddressWindows(
Op, DAG);
3534 assert(
TT.isOSBinFormatELF() &&
"Only ELF implemented here");
3540 return LowerToTLSGeneralDynamicModel(GA, DAG);
3543 return LowerToTLSExecModels(GA, DAG, model);
3552 while (!Worklist.
empty()) {
3560 if (!
I ||
I->getParent()->getParent() !=
F)
3589 if (!GVar || !GVar->hasInitializer() ||
3590 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3591 !GVar->hasLocalLinkage())
3596 auto *
Init = GVar->getInitializer();
3598 Init->needsDynamicRelocation())
3610 unsigned RequiredPadding = 4 - (
Size % 4);
3611 bool PaddingPossible =
3612 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3617 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3641 if (RequiredPadding != 4) {
3646 while (RequiredPadding--)
3658 ++NumConstpoolPromoted;
3659 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3664 if (!(GV = GA->getAliaseeObject()))
3667 return V->isConstant();
3676 return LowerGlobalAddressWindows(
Op, DAG);
3678 return LowerGlobalAddressELF(
Op, DAG);
3680 return LowerGlobalAddressDarwin(
Op, DAG);
3692 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3705 }
else if (Subtarget->isROPI() && IsRO) {
3710 }
else if (Subtarget->isRWPI() && !IsRO) {
3713 if (Subtarget->useMovt()) {
3716 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3718 ARMConstantPoolValue *CPV =
3721 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3735 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3736 if (Subtarget->useMovt())
3740 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3744 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3753 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3754 "ROPI/RWPI not currently supported for Darwin");
3759 if (Subtarget->useMovt())
3770 if (Subtarget->isGVIndirectSymbol(GV))
3779 "non-Windows COFF is not supported");
3780 assert(Subtarget->useMovt() &&
3781 "Windows on ARM expects to use movw/movt");
3782 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3783 "ROPI/RWPI not currently supported for Windows");
3790 else if (!TM.shouldAssumeDSOLocal(GV))
3813 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3814 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3815 Op.getOperand(1), Val);
3821 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3828 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3832SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3835 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3839 case Intrinsic::arm_gnu_eabi_mcount: {
3845 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3846 const uint32_t *
Mask =
3848 assert(Mask &&
"Missing call preserved mask for calling convention");
3853 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3857 if (Subtarget->isThumb())
3860 ARM::tBL_PUSHLR, dl, ResultTys,
3861 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3862 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3866 {ReturnAddress, Callee, RegisterMask, Chain}),
3875 unsigned IntNo =
Op.getConstantOperandVal(0);
3879 case Intrinsic::localaddress: {
3881 const auto *RegInfo = Subtarget->getRegisterInfo();
3882 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
3884 Op.getSimpleValueType());
3886 case Intrinsic::eh_recoverfp: {
3892 "llvm.eh.recoverfp must take a function as the first argument");
3893 const auto *RegInfo = Subtarget->getRegisterInfo();
3896 MachineBasicBlock &
MBB = *MF.
begin();
3902 case Intrinsic::thread_pointer: {
3904 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3906 case Intrinsic::arm_cls: {
3910 const SDValue &Operand =
Op.getOperand(1);
3911 const EVT VTy =
Op.getValueType();
3914 case Intrinsic::arm_cls64: {
3920 case Intrinsic::arm_neon_vcls:
3921 case Intrinsic::arm_mve_vcls: {
3924 const EVT VTy =
Op.getValueType();
3927 case Intrinsic::eh_sjlj_lsda: {
3929 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3934 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3935 ARMConstantPoolValue *CPV =
3939 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3944 if (IsPositionIndependent) {
3946 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3950 case Intrinsic::arm_neon_vabs:
3953 case Intrinsic::arm_neon_vabds:
3954 if (
Op.getValueType().isInteger())
3956 Op.getOperand(1),
Op.getOperand(2));
3958 case Intrinsic::arm_neon_vabdu:
3960 Op.getOperand(1),
Op.getOperand(2));
3961 case Intrinsic::arm_neon_vmulls:
3962 case Intrinsic::arm_neon_vmullu: {
3963 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3964 ? ARMISD::VMULLs : ARMISD::VMULLu;
3965 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3966 Op.getOperand(1),
Op.getOperand(2));
3968 case Intrinsic::arm_neon_vminnm:
3969 case Intrinsic::arm_neon_vmaxnm: {
3970 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3972 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3973 Op.getOperand(1),
Op.getOperand(2));
3975 case Intrinsic::arm_neon_vminu:
3976 case Intrinsic::arm_neon_vmaxu: {
3977 if (
Op.getValueType().isFloatingPoint())
3979 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3981 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3982 Op.getOperand(1),
Op.getOperand(2));
3984 case Intrinsic::arm_neon_vmins:
3985 case Intrinsic::arm_neon_vmaxs: {
3987 if (!
Op.getValueType().isFloatingPoint()) {
3988 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3990 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3991 Op.getOperand(1),
Op.getOperand(2));
3993 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3995 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3996 Op.getOperand(1),
Op.getOperand(2));
3998 case Intrinsic::arm_neon_vtbl1:
3999 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
4000 Op.getOperand(1),
Op.getOperand(2));
4001 case Intrinsic::arm_neon_vtbl2:
4002 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
4003 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4004 case Intrinsic::arm_mve_pred_i2v:
4005 case Intrinsic::arm_mve_pred_v2i:
4006 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
4008 case Intrinsic::arm_mve_vreinterpretq:
4009 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
4011 case Intrinsic::arm_mve_lsll:
4012 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
4013 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4014 case Intrinsic::arm_mve_asrl:
4015 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
4016 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4017 case Intrinsic::arm_mve_vsli:
4018 return DAG.
getNode(ARMISD::VSLIIMM, SDLoc(
Op),
Op->getVTList(),
4019 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4020 case Intrinsic::arm_mve_vsri:
4021 return DAG.
getNode(ARMISD::VSRIIMM, SDLoc(
Op),
Op->getVTList(),
4022 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4033 if (!Subtarget->hasDataBarrier()) {
4037 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4038 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4039 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
4049 }
else if (Subtarget->preferISHSTBarriers() &&
4058 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4066 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4068 return Op.getOperand(0);
4071 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4073 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4075 return Op.getOperand(0);
4077 unsigned isData =
Op.getConstantOperandVal(4);
4078 if (Subtarget->isThumb()) {
4080 isRead = ~isRead & 1;
4081 isData = ~isData & 1;
4084 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4099 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4107 const SDLoc &dl)
const {
4109 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4113 RC = &ARM::tGPRRegClass;
4115 RC = &ARM::GPRRegClass;
4129 MVT::i32, dl, Root, FIN,
4135 if (!Subtarget->isLittle())
4137 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4150 const Value *OrigArg,
4151 unsigned InRegsParamRecordIdx,
4152 int ArgOffset,
unsigned ArgSize)
const {
4166 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4167 unsigned RBegin, REnd;
4172 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4177 ArgOffset = -4 * (ARM::R4 - RBegin);
4187 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4191 MachinePointerInfo(OrigArg, 4 * i));
4196 if (!MemOps.
empty())
4205 unsigned TotalArgRegsSaveSize,
4206 bool ForceMutable)
const {
4208 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4217 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4221bool ARMTargetLowering::splitValueIntoRegisterParts(
4223 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4225 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4237SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4239 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4240 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4253SDValue ARMTargetLowering::LowerFormalArguments(
4260 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4269 unsigned CurArgIdx = 0;
4281 unsigned ArgRegBegin = ARM::R4;
4282 for (
const CCValAssign &VA : ArgLocs) {
4288 if (!
Flags.isByVal())
4292 unsigned RBegin, REnd;
4294 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4300 int lastInsIndex = -1;
4304 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4307 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4311 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4312 CCValAssign &VA = ArgLocs[i];
4313 if (Ins[VA.
getValNo()].isOrigArg()) {
4314 std::advance(CurOrigArg,
4315 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4316 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4327 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4334 MVT::f64, dl, Chain, FIN,
4337 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4345 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4349 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4350 RC = &ARM::HPRRegClass;
4351 else if (RegVT == MVT::f32)
4352 RC = &ARM::SPRRegClass;
4353 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4354 RegVT == MVT::v4bf16)
4355 RC = &ARM::DPRRegClass;
4356 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4357 RegVT == MVT::v8bf16)
4358 RC = &ARM::QPRRegClass;
4359 else if (RegVT == MVT::i32)
4361 : &ARM::GPRRegClass;
4398 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4407 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4413 if (index != lastInsIndex)
4415 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4421 if (
Flags.isByVal()) {
4422 assert(Ins[index].isOrigArg() &&
4423 "Byval arguments cannot be implicit");
4427 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4461 lastInsIndex = index;
4468 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4469 TotalArgRegsSaveSize);
4473 "secure entry function must not be variadic", dl.
getDebugLoc()));
4483 assert(StackAlign &&
"data layout string is missing stack alignment");
4484 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4493 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4502 return CFP->getValueAPF().isPosZero();
4505 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4506 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4509 return CFP->getValueAPF().isPosZero();
4512 Op->getValueType(0) == MVT::f64) {
4516 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4525 if (
Op->getFlags().hasNoSignedWrap())
4541 (isIntEqualitySetCC(CC) ||
4551 if (ST.isThumb1Only() || !
Op.hasOneUse())
4554 unsigned Opc =
Op.getOpcode();
4557 return ShiftAmt->getZExtValue() <= 31 ? 1 : 0;
4560 return ST.isThumb() ? 0 : 1;
4568 return ST.isThumb() ? 0 : 1;
4578 const SDLoc &dl)
const {
4580 unsigned C = RHSC->getZExtValue();
4638 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4642 unsigned Mask =
LHS.getConstantOperandVal(1);
4644 uint64_t RHSV = RHSC->getZExtValue();
4645 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4647 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4661 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4664 LHS.getConstantOperandVal(1) < 31) {
4665 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4675 unsigned CompareType;
4678 CompareType = ARMISD::CMP;
4683 CompareType = ARMISD::CMPZ;
4692 if (CompareType != ARMISD::CMPZ &&
isCMN(
RHS, CC, DAG)) {
4693 CompareType = ARMISD::CMN;
4695 }
else if (CompareType != ARMISD::CMPZ &&
isCMN(
LHS, CC, DAG)) {
4696 CompareType = ARMISD::CMN;
4710 if (CompareType == ARMISD::CMP)
4738 bool Signaling)
const {
4739 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4745 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4754std::pair<SDValue, SDValue>
4757 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4769 switch (
Op.getOpcode()) {
4821 return std::make_pair(
Value, OverflowCmp);
4834 return Cmp.getValue(1);
4862 return DAG.
getNode(ARMISD::CMOV,
DL, VT, Zero, One, ARMcc, Flags);
4874 EVT VT =
Op.getValueType();
4875 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4878 switch (
Op.getOpcode()) {
4892 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4898 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4901 ARMcc, OverflowCmp);
4911 EVT VT =
Op.getValueType();
4912 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4922 switch (
Op->getOpcode()) {
4924 NewOpcode = ARMISD::UQADD8b;
4927 NewOpcode = ARMISD::QADD8b;
4930 NewOpcode = ARMISD::UQSUB8b;
4933 NewOpcode = ARMISD::QSUB8b;
4938 switch (
Op->getOpcode()) {
4940 NewOpcode = ARMISD::UQADD16b;
4943 NewOpcode = ARMISD::QADD16b;
4946 NewOpcode = ARMISD::UQSUB16b;
4949 NewOpcode = ARMISD::QSUB16b;
4957 DAG.
getNode(NewOpcode, dl, MVT::i32,
4968 unsigned Opc =
Cond.getOpcode();
4970 if (
Cond.getResNo() == 1 &&
4978 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4979 EVT VT =
Op.getValueType();
4981 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4989 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4990 const ConstantSDNode *CMOVTrue =
4992 const ConstantSDNode *CMOVFalse =
4995 if (CMOVTrue && CMOVFalse) {
5001 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5003 False = SelectFalse;
5004 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5010 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5011 Cond.getOperand(3), DAG);
5021 bool &swpCmpOps,
bool &swpVselOps) {
5049 swpCmpOps = !swpCmpOps;
5050 swpVselOps = !swpVselOps;
5073 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5075 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5077 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5091 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5112 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5114 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5135 EVT VT =
Op.getValueType();
5157 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5170 int64_t PosVal = std::max(Val1, Val2);
5171 int64_t NegVal = std::min(Val1, Val2);
5183 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5186 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5218 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5223 if (*K != KTmp || V != VTmp)
5234bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5236 return !Subtarget->hasVFP2Base();
5238 return !Subtarget->hasFP64();
5240 return !Subtarget->hasFullFP16();
5248 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5256 if (TVal == ~FVal) {
5257 Opcode = ARMISD::CSINV;
5258 }
else if (TVal == ~FVal + 1) {
5259 Opcode = ARMISD::CSNEG;
5260 }
else if (TVal + 1 == FVal) {
5261 Opcode = ARMISD::CSINC;
5262 }
else if (TVal == FVal + 1) {
5263 Opcode = ARMISD::CSINC;
5266 InvertCond = !InvertCond;
5273 if (Opcode != ARMISD::CSINC &&
5277 InvertCond = !InvertCond;
5283 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5286 InvertCond = !InvertCond;
5293 EVT VT =
Op.getValueType();
5297 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5309 if (VT == MVT::i32 &&
5328 if (
Op.getValueType().isInteger()) {
5336 LHS.getValueType() ==
RHS.getValueType()) {
5337 EVT VT =
LHS.getValueType();
5343 Shift = DAG.
getNOT(dl, Shift, VT);
5355 if (
LHS.getValueType() == MVT::i32) {
5359 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5365 EVT VT =
Op.getValueType();
5366 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5370 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5375 if (!
RHS.getNode()) {
5381 if (
LHS.getValueType() == MVT::i32) {
5392 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5393 TrueVal.getValueType() == MVT::f32 ||
5394 TrueVal.getValueType() == MVT::f64)) {
5408 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5418 if (Subtarget->hasFPARMv8Base() &&
5420 (
TrueVal.getValueType() == MVT::f16 ||
5421 TrueVal.getValueType() == MVT::f32 ||
5422 TrueVal.getValueType() == MVT::f64)) {
5423 bool swpCmpOps =
false;
5424 bool swpVselOps =
false;
5438 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5441 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5451 if (!
N->hasOneUse())
5454 if (!
N->getNumValues())
5456 EVT VT =
Op.getValueType();
5457 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5474 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5475 Ld->getPointerInfo(), Ld->getAlign(),
5476 Ld->getMemOperand()->getFlags());
5492 SDValue Ptr = Ld->getBasePtr();
5494 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5495 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5500 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5501 Ld->getPointerInfo().getWithOffset(4),
5503 Ld->getMemOperand()->getFlags());
5521 bool LHSSeenZero =
false;
5523 bool RHSSeenZero =
false;
5525 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5536 if (
LHS.getValueType() == MVT::f32) {
5542 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5554 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5555 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5570 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5589 unsigned Opc =
Cond.getOpcode();
5591 !Subtarget->isThumb1Only();
5592 if (
Cond.getResNo() == 1 &&
5602 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5607 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5622 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5627 if (!
RHS.getNode()) {
5635 unsigned Opc =
LHS.getOpcode();
5637 !Subtarget->isThumb1Only();
5649 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5656 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5660 if (
LHS.getValueType() == MVT::i32) {
5663 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5666 SDNodeFlags
Flags =
Op->getFlags();
5667 if (
Flags.hasNoNaNs() &&
5672 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5686 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5700 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5703 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5708 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5709 Addr,
Op.getOperand(2), JTI);
5713 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5717 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5720 DAG.
getLoad(PTy, dl, Chain, Addr,
5723 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5728 EVT VT =
Op.getValueType();
5731 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5732 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5740 const EVT OpTy =
Op.getOperand(0).getValueType();
5741 if (
OpTy == MVT::v4f32)
5743 else if (
OpTy == MVT::v4f16 && HasFullFP16)
5745 else if (
OpTy == MVT::v8f16 && HasFullFP16)
5750 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5753 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5758 EVT VT =
Op.getValueType();
5762 bool IsStrict =
Op->isStrictFPOpcode();
5763 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5765 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5778 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5779 CallOptions, Loc, Chain);
5788 EVT VT =
Op.getValueType();
5790 EVT FromVT =
Op.getOperand(0).getValueType();
5792 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5794 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5795 Subtarget->hasFP64())
5797 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5798 Subtarget->hasFullFP16())
5800 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5801 Subtarget->hasMVEFloatOps())
5803 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5804 Subtarget->hasMVEFloatOps())
5807 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5824 EVT VT =
Op.getValueType();
5827 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5833 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5834 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5835 "Invalid type for custom lowering!");
5840 if (VT == MVT::v4f32)
5841 DestVecType = MVT::v4i32;
5842 else if (VT == MVT::v4f16 && HasFullFP16)
5843 DestVecType = MVT::v4i16;
5844 else if (VT == MVT::v8f16 && HasFullFP16)
5845 DestVecType = MVT::v8i16;
5851 switch (
Op.getOpcode()) {
5863 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5868 EVT VT =
Op.getValueType();
5872 bool IsStrict =
Op->isStrictFPOpcode();
5873 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5875 if (isUnsupportedFloatingType(VT)) {
5886 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5887 CallOptions, Loc, Chain);
5899 EVT VT =
Op.getValueType();
5903 bool UseNEON = !InGPR && Subtarget->hasNEON();
5910 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5917 if (SrcVT == MVT::f32) {
5920 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5923 }
else if (VT == MVT::f32)
5924 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5939 if (VT == MVT::f32) {
5951 if (SrcVT == MVT::f64)
5960 if (VT == MVT::f32) {
5973 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5981 EVT VT =
Op.getValueType();
5983 unsigned Depth =
Op.getConstantOperandVal(0);
5985 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5989 MachinePointerInfo());
5998 const ARMBaseRegisterInfo &ARI =
5999 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
6004 EVT VT =
Op.getValueType();
6006 unsigned Depth =
Op.getConstantOperandVal(0);
6011 MachinePointerInfo());
6019 return StringSwitch<Register>(
RegName)
6020 .Case(
"sp", ARM::SP)
6031 assert(
N->getValueType(0) == MVT::i64
6032 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6035 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6075 const APInt &APIntIndex = Index->getAPIntValue();
6077 NewIndex *= APIntIndex;
6106 EVT SrcVT =
Op.getValueType();
6107 EVT DstVT =
N->getValueType(0);
6109 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6110 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6111 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6114 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6115 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6116 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6123 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6135 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6143 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6145 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6147 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6167 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6176 EVT VT =
Op.getValueType();
6198 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6208 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6219 EVT VT =
Op.getValueType();
6240 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6261 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6313 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6341 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6371 EVT VT =
N->getValueType(0);
6372 if (VT.
isVector() && ST->hasNEON()) {
6381 if (ElemTy == MVT::i8) {
6389 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6392 unsigned NumBits = ElemTy.getSizeInBits();
6394 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6404 if (ElemTy == MVT::i64) {
6417 if (!ST->hasV6T2Ops())
6426 EVT VT =
N->getValueType(0);
6429 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6430 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6431 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6432 "Unexpected type for custom ctpop lowering");
6440 unsigned EltSize = 8;
6463 Op =
Op.getOperand(0);
6465 APInt SplatBits, SplatUndef;
6466 unsigned SplatBitSize;
6469 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6471 SplatBitSize > ElementBits)
6482 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6486 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6497 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6502 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6503 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6512 EVT VT =
N->getValueType(0);
6527 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6529 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6534 "unexpected vector shift opcode");
6536 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6537 unsigned VShiftOpc =
6538 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6539 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6545 EVT ShiftVT =
N->getOperand(1).getValueType();
6548 unsigned VShiftOpc =
6549 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6550 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6555 EVT VT =
N->getValueType(0);
6564 "Unknown shift to lower!");
6566 unsigned ShOpc =
N->getOpcode();
6567 if (ST->hasMVEIntegerOps()) {
6569 unsigned ShPartsOpc = ARMISD::LSLL;
6590 ShPartsOpc = ARMISD::LSRL;
6592 ShPartsOpc = ARMISD::ASRL;
6597 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6611 if (ST->isThumb1Only())
6616 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6620 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6624 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6632 bool Invert =
false;
6639 EVT VT =
Op.getValueType();
6647 assert(ST->hasMVEIntegerOps() &&
6648 "No hardware support for integer vector comparison!");
6650 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6671 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6675 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6685 switch (SetCCOpcode) {
6689 if (ST->hasMVEFloatOps()) {
6692 Invert =
true; [[fallthrough]];
6697 case ISD::SETLT: Swap =
true; [[fallthrough]];
6701 case ISD::SETLE: Swap =
true; [[fallthrough]];
6717 Result = DAG.
getNOT(dl, Result, VT);
6720 case ISD::SETUO: Invert =
true; [[fallthrough]];
6729 Result = DAG.
getNOT(dl, Result, VT);
6735 switch (SetCCOpcode) {
6738 if (ST->hasMVEIntegerOps()) {
6741 Invert =
true; [[fallthrough]];
6744 case ISD::SETLT: Swap =
true; [[fallthrough]];
6746 case ISD::SETLE: Swap =
true; [[fallthrough]];
6763 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6766 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6771 Result = DAG.
getNOT(dl, Result, VT);
6796 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6799 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6805 Result = DAG.
getNOT(dl, Result, VT);
6814 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6831 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6842 unsigned OpCmode, Imm;
6853 switch (SplatBitSize) {
6858 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6861 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6866 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6867 if ((SplatBits & ~0xff) == 0) {
6873 if ((SplatBits & ~0xff00) == 0) {
6876 Imm = SplatBits >> 8;
6886 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6887 if ((SplatBits & ~0xff) == 0) {
6893 if ((SplatBits & ~0xff00) == 0) {
6896 Imm = SplatBits >> 8;
6899 if ((SplatBits & ~0xff0000) == 0) {
6902 Imm = SplatBits >> 16;
6905 if ((SplatBits & ~0xff000000) == 0) {
6908 Imm = SplatBits >> 24;
6915 if ((SplatBits & ~0xffff) == 0 &&
6916 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6919 Imm = SplatBits >> 8;
6927 if ((SplatBits & ~0xffffff) == 0 &&
6928 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6931 Imm = SplatBits >> 16;
6947 unsigned ImmMask = 1;
6949 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6950 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6952 }
else if ((SplatBits & BitMask) != 0) {
6961 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6975 EVT VT =
Op.getValueType();
6976 bool IsDouble = (VT == MVT::f64);
6982 if (
ST->genExecuteOnly()) {
6984 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6985 "Unexpected architecture");
7003 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
7008 if (!
ST->hasVFP3Base())
7013 if (IsDouble && !Subtarget->hasFP64())
7020 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7038 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7047 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7101 unsigned ExpectedElt = Imm;
7102 for (
unsigned i = 1; i < NumElts; ++i) {
7106 if (ExpectedElt == NumElts)
7109 if (M[i] < 0)
continue;
7110 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7118 bool &ReverseVEXT,
unsigned &Imm) {
7120 ReverseVEXT =
false;
7131 unsigned ExpectedElt = Imm;
7132 for (
unsigned i = 1; i < NumElts; ++i) {
7136 if (ExpectedElt == NumElts * 2) {
7141 if (M[i] < 0)
continue;
7142 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7157 return VT == MVT::v8i8 && M.size() == 8;
7162 if (Mask.size() == Elements * 2)
7163 return Index / Elements;
7164 return Mask[Index] == 0 ? 0 : 1;
7194 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7202 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7204 for (
unsigned j = 0; j < NumElts; j += 2) {
7205 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7206 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7211 if (M.size() == NumElts*2)
7226 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7229 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7231 for (
unsigned j = 0; j < NumElts; j += 2) {
7232 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7233 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7238 if (M.size() == NumElts*2)
7258 if (M.size() != NumElts && M.size() != NumElts*2)
7261 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7263 for (
unsigned j = 0; j < NumElts; ++j) {
7264 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7269 if (M.size() == NumElts*2)
7288 if (M.size() != NumElts && M.size() != NumElts*2)
7291 unsigned Half = NumElts / 2;
7292 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7294 for (
unsigned j = 0; j < NumElts; j += Half) {
7295 unsigned Idx = WhichResult;
7296 for (
unsigned k = 0; k < Half; ++k) {
7297 int MIdx = M[i + j + k];
7298 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7305 if (M.size() == NumElts*2)
7329 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7332 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7334 unsigned Idx = WhichResult * NumElts / 2;
7335 for (
unsigned j = 0; j < NumElts; j += 2) {
7336 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7337 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7343 if (M.size() == NumElts*2)
7362 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7365 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7367 unsigned Idx = WhichResult * NumElts / 2;
7368 for (
unsigned j = 0; j < NumElts; j += 2) {
7369 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7370 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7376 if (M.size() == NumElts*2)
7389 unsigned &WhichResult,
7392 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7393 return ARMISD::VTRN;
7394 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7395 return ARMISD::VUZP;
7396 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7397 return ARMISD::VZIP;
7401 return ARMISD::VTRN;
7403 return ARMISD::VUZP;
7405 return ARMISD::VZIP;
7414 if (NumElts != M.size())
7418 for (
unsigned i = 0; i != NumElts; ++i)
7419 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7428 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7436 int Ofs = Top ? 1 : 0;
7437 int Upper = SingleSource ? 0 : NumElts;
7438 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7439 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7441 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7450 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7459 unsigned Offset = Top ? 0 : 1;
7460 unsigned N = SingleSource ? 0 : NumElts;
7461 for (
unsigned i = 0; i < NumElts; i += 2) {
7462 if (M[i] >= 0 && M[i] != (
int)i)
7464 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7473 if (NumElts != M.size())
7481 unsigned Off0 = rev ? NumElts / 2 : 0;
7482 unsigned Off1 = rev ? 0 : NumElts / 2;
7483 for (
unsigned i = 0; i < NumElts; i += 2) {
7484 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7486 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7502 if (!ST->hasMVEFloatOps())
7507 if (VT != MVT::v8f16)
7528 for (
unsigned i = 1; i < 4; i++) {
7543 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7555 if (!ST->hasMVEFloatOps())
7560 if (VT != MVT::v4f32)
7576 for (
unsigned i = 1; i < 4; i++) {
7587 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7599 Val =
N->getAsZExtVal();
7601 if (ST->isThumb1Only()) {
7602 if (Val <= 255 || ~Val <= 255)
7614 EVT VT =
Op.getValueType();
7616 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7620 unsigned BitsPerBool;
7624 }
else if (NumElts == 4) {
7627 }
else if (NumElts == 8) {
7630 }
else if (NumElts == 16) {
7641 return U.get().isUndef() || U.get() == FirstOp;
7645 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7649 unsigned Bits32 = 0;
7650 for (
unsigned i = 0; i < NumElts; ++i) {
7654 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7656 Bits32 |= BoolMask << (i * BitsPerBool);
7662 for (
unsigned i = 0; i < NumElts; ++i) {
7675 if (!ST->hasMVEIntegerOps())
7679 EVT VT =
Op.getValueType();
7689 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7693 for (
unsigned I = 2;
I < NumElts;
I++) {
7709 switch (
N->getOpcode()) {
7720 return N->getOperand(1).getNode() ==
Op;
7722 switch (
N->getConstantOperandVal(0)) {
7723 case Intrinsic::arm_mve_add_predicated:
7724 case Intrinsic::arm_mve_mul_predicated:
7725 case Intrinsic::arm_mve_qadd_predicated:
7726 case Intrinsic::arm_mve_vhadd:
7727 case Intrinsic::arm_mve_hadd_predicated:
7728 case Intrinsic::arm_mve_vqdmulh:
7729 case Intrinsic::arm_mve_qdmulh_predicated:
7730 case Intrinsic::arm_mve_vqrdmulh:
7731 case Intrinsic::arm_mve_qrdmulh_predicated:
7732 case Intrinsic::arm_mve_vqdmull:
7733 case Intrinsic::arm_mve_vqdmull_predicated:
7735 case Intrinsic::arm_mve_sub_predicated:
7736 case Intrinsic::arm_mve_qsub_predicated:
7737 case Intrinsic::arm_mve_vhsub:
7738 case Intrinsic::arm_mve_hsub_predicated:
7739 return N->getOperand(2).getNode() ==
Op;
7754 EVT VT =
Op.getValueType();
7762 APInt SplatBits, SplatUndef;
7763 unsigned SplatBitSize;
7765 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7772 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7774 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7775 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7776 : SplatBitSize == 16 ? MVT::v8i16
7780 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7783 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7784 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7789 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7793 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7797 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7799 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7803 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7807 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7811 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7817 if (
ST->hasMVEIntegerOps() &&
7818 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7819 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7820 : SplatBitSize == 16 ? MVT::v8i16
7824 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7837 bool isOnlyLowElement =
true;
7838 bool usesOnlyOneValue =
true;
7839 bool hasDominantValue =
false;
7844 DenseMap<SDValue, unsigned> ValueCounts;
7846 for (
unsigned i = 0; i < NumElts; ++i) {
7851 isOnlyLowElement =
false;
7855 unsigned &
Count = ValueCounts[
V];
7858 if (++
Count > (NumElts / 2)) {
7859 hasDominantValue =
true;
7863 if (ValueCounts.
size() != 1)
7864 usesOnlyOneValue =
false;
7865 if (!
Value.getNode() && !ValueCounts.
empty())
7868 if (ValueCounts.
empty())
7874 (VT != MVT::v8f16 ||
ST->hasFullFP16()))
7881 if (hasDominantValue && EltSize <= 32) {
7890 ConstantSDNode *constIndex;
7897 if (VT !=
Value->getOperand(0).getValueType()) {
7900 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7905 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7910 if (!usesOnlyOneValue) {
7913 for (
unsigned I = 0;
I < NumElts; ++
I) {
7918 Ops.push_back(
Op.getOperand(
I));
7928 assert(FVT == MVT::f32 || FVT == MVT::f16);
7929 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7930 for (
unsigned i = 0; i < NumElts; ++i)
7935 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7939 if (usesOnlyOneValue) {
7942 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7966 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7986 if (EltSize >= 32) {
7992 for (
unsigned i = 0; i < NumElts; ++i)
8005 (VT == MVT::v8f16 && !
ST->hasFullFP16())) {
8007 for (
unsigned i = 0 ; i < NumElts; ++i) {
8026 EVT VT =
Op.getValueType();
8029 struct ShuffleSourceInfo {
8031 unsigned MinElt = std::numeric_limits<unsigned>::max();
8032 unsigned MaxElt = 0;
8042 int WindowScale = 1;
8044 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8052 for (
unsigned i = 0; i < NumElts; ++i) {
8067 SDValue SourceVec =
V.getOperand(0);
8069 if (Source == Sources.
end())
8073 unsigned EltNo =
V.getConstantOperandVal(1);
8080 if (Sources.
size() > 2)
8086 for (
auto &Source : Sources) {
8087 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8088 if (SrcEltTy.
bitsLT(SmallestEltTy))
8089 SmallestEltTy = SrcEltTy;
8091 unsigned ResMultiplier =
8099 for (
auto &Src : Sources) {
8100 EVT SrcVT = Src.ShuffleVec.getValueType();
8104 if (SrcVTSize == VTSize)
8113 if (SrcVTSize < VTSize) {
8114 if (2 * SrcVTSize != VTSize)
8120 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8124 if (SrcVTSize != 2 * VTSize)
8127 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8132 if (Src.MinElt >= NumSrcElts) {
8137 Src.WindowBase = -NumSrcElts;
8138 }
else if (Src.MaxElt < NumSrcElts) {
8152 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8155 Src.WindowBase = -Src.MinElt;
8162 for (
auto &Src : Sources) {
8163 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8164 if (SrcEltTy == SmallestEltTy)
8167 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8169 Src.WindowBase *= Src.WindowScale;
8174 for (
auto Src : Sources)
8175 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8183 if (
Entry.isUndef())
8192 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8195 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8199 int *LaneMask = &
Mask[i * ResMultiplier];
8201 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8202 ExtractBase += NumElts * (Src - Sources.begin());
8203 for (
int j = 0;
j < LanesDefined; ++
j)
8204 LaneMask[j] = ExtractBase + j;
8210 assert(Sources.size() <= 2 &&
"Too many sources!");
8213 for (
unsigned i = 0; i < Sources.size(); ++i)
8220 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8242 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8262 unsigned PFIndexes[4];
8263 for (
unsigned i = 0; i != 4; ++i) {
8267 PFIndexes[i] = M[i];
8271 unsigned PFTableIndex =
8272 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8274 unsigned Cost = (PFEntry >> 30);
8280 bool ReverseVEXT, isV_UNDEF;
8281 unsigned Imm, WhichResult;
8284 if (EltSize >= 32 ||
8291 else if (Subtarget->hasNEON() &&
8296 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8299 else if (Subtarget->hasMVEIntegerOps() &&
8303 else if (Subtarget->hasMVEIntegerOps() &&
8317 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8318 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8319 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8322 if (LHSID == (1*9+2)*9+3)
return LHS;
8323 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8337 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8340 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8343 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8348 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8353 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8380 for (
int I : ShuffleMask)
8384 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8,
V1,
8387 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8,
V1, V2,
8393 EVT VT =
Op.getValueType();
8395 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8396 "Expect an v8i16/v16i8 type");
8402 std::vector<int> NewMask;
8406 NewMask.push_back(i);
8436 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8446 if (VT != MVT::v16i1)
8447 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8462 EVT VT =
Op.getValueType();
8466 assert(ST->hasMVEIntegerOps() &&
8467 "No support for vector shuffle of boolean predicates");
8477 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8493 "Expected identical vector type in expanded i1 shuffle!");
8497 PredAsVector2, ShuffleMask);
8502 if (VT == MVT::v2i1) {
8503 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8506 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8508 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8519 EVT VT =
Op.getValueType();
8523 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8524 "Unexpected vector type");
8526 int QuarterSize = NumElts / 4;
8535 for (
int i = 0; i <
Length; i++) {
8536 if (ShuffleMask[Start + i] >= 0) {
8537 if (ShuffleMask[Start + i] %
Length != i)
8539 MovIdx = ShuffleMask[Start + i] /
Length;
8547 for (
int i = 1; i <
Length; i++) {
8548 if (ShuffleMask[Start + i] >= 0 &&
8549 (ShuffleMask[Start + i] /
Length != MovIdx ||
8550 ShuffleMask[Start + i] %
Length != i))
8556 for (
int Part = 0; Part < 4; ++Part) {
8558 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8572 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8577 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8579 for (
int Part = 0; Part < 4; ++Part)
8580 for (
int i = 0; i < QuarterSize; i++)
8582 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8584 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8587 for (
int Part = 0; Part < 4; ++Part)
8603 EVT VT =
Op.getValueType();
8615 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8619 if (Mask[i] != i + BaseOffset) {
8620 if (OffElement == -1)
8626 return NonUndef > 2 && OffElement != -1;
8630 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8632 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8643 ShuffleMask[OffElement] < (
int)NumElts ?
V1 : V2,
8654 EVT VT =
Op.getValueType();
8658 if (ST->hasMVEIntegerOps() && EltSize == 1)
8669 if (EltSize <= 32) {
8673 if (Lane == -1) Lane = 0;
8677 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8684 bool IsScalarToVector =
true;
8685 for (
unsigned i = 1, e =
V1.getNumOperands(); i != e; ++i)
8686 if (!
V1.getOperand(i).isUndef()) {
8687 IsScalarToVector =
false;
8690 if (IsScalarToVector)
8691 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8693 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
V1,
8697 bool ReverseVEXT =
false;
8699 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8702 return DAG.
getNode(ARMISD::VEXT, dl, VT,
V1, V2,
8707 return DAG.
getNode(ARMISD::VREV64, dl, VT,
V1);
8709 return DAG.
getNode(ARMISD::VREV32, dl, VT,
V1);
8711 return DAG.
getNode(ARMISD::VREV16, dl, VT,
V1);
8723 unsigned WhichResult = 0;
8724 bool isV_UNDEF =
false;
8725 if (ST->hasNEON()) {
8727 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8734 if (ST->hasMVEIntegerOps()) {
8736 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2,
V1,
8739 return DAG.
getNode(ARMISD::VMOVN, dl, VT,
V1, V2,
8769 }) &&
"Unexpected shuffle index into UNDEF operand!");
8772 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8775 assert((WhichResult == 0) &&
8776 "In-place shuffle of concat can only have one result!");
8785 if (ST->hasMVEIntegerOps() && EltSize <= 32 &&
8786 (ST->hasFullFP16() || VT != MVT::v8f16)) {
8790 for (
bool Top : {
false,
true}) {
8791 for (
bool SingleSource : {
false,
true}) {
8792 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8797 SingleSource ?
V1 : V2);
8813 unsigned PFIndexes[4];
8814 for (
unsigned i = 0; i != 4; ++i) {
8815 if (ShuffleMask[i] < 0)
8818 PFIndexes[i] = ShuffleMask[i];
8822 unsigned PFTableIndex =
8823 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8825 unsigned Cost = (PFEntry >> 30);
8831 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8832 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8842 if (EltSize >= 32) {
8850 for (
unsigned i = 0; i < NumElts; ++i) {
8851 if (ShuffleMask[i] < 0)
8855 ShuffleMask[i] < (
int)NumElts ?
V1 : V2,
8863 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8867 if (ST->hasNEON() && VT == MVT::v8i8)
8871 if (ST->hasMVEIntegerOps())
8876 if (VT == MVT::v8f16 && !ST->hasFullFP16()) {
8878 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(0));
8880 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(1));
8882 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuf);
8890 EVT VecVT =
Op.getOperand(0).getValueType();
8893 assert(ST->hasMVEIntegerOps() &&
8894 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8897 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8898 unsigned Lane =
Op.getConstantOperandVal(2);
8899 unsigned LaneWidth =
8901 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8906 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8919 if (Subtarget->hasMVEIntegerOps() &&
8920 Op.getValueType().getScalarSizeInBits() == 1)
8944 IVecIn, IElt, Lane);
8953 EVT VecVT =
Op.getOperand(0).getValueType();
8956 assert(ST->hasMVEIntegerOps() &&
8957 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8960 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8961 unsigned Lane =
Op.getConstantOperandVal(1);
8962 unsigned LaneWidth =
8984 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8993 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8994 "Unexpected custom CONCAT_VECTORS lowering");
8996 "Unexpected custom CONCAT_VECTORS lowering");
8997 assert(ST->hasMVEIntegerOps() &&
8998 "CONCAT_VECTORS lowering only supported for MVE");
9001 EVT Op1VT =
V1.getValueType();
9002 EVT Op2VT = V2.getValueType();
9003 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9004 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9005 "Unexpected i1 concat operations!");
9018 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9023 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
9032 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9033 EVT NewVT = NewV.getValueType();
9034 EVT ConcatVT = ConVec.getValueType();
9035 unsigned ExtScale = 1;
9036 if (NewVT == MVT::v2f64) {
9037 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
9050 ConVec = ExtractInto(NewV1, ConVec, j);
9051 ConVec = ExtractInto(NewV2, ConVec, j);
9055 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
9061 while (ConcatOps.
size() > 1) {
9062 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
9065 ConcatOps[
I / 2] = ConcatPair(
V1, V2);
9069 return ConcatOps[0];
9074 EVT VT =
Op->getValueType(0);
9080 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9081 "unexpected CONCAT_VECTORS");
9102 EVT VT =
Op.getValueType();
9103 EVT Op1VT =
V1.getValueType();
9108 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9109 assert(ST->hasMVEIntegerOps() &&
9110 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9120 EVT SubVT = MVT::v4i32;
9122 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9132 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
9137 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9146 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9153 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9154 EVT VT =
N->getValueType(0);
9155 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9156 "Expected a vector i1 type!");
9158 EVT FromVT =
Op.getValueType();
9169 if (!Subtarget->hasMVEIntegerOps())
9172 EVT ToVT =
N->getValueType(0);
9215 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9217 EVT FromVT =
N->getOperand(0).getValueType();
9218 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9229 if (!Subtarget->hasMVEIntegerOps())
9234 EVT ToVT =
N->getValueType(0);
9235 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9238 EVT FromVT =
Op.getValueType();
9239 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9253 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9254 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9266 EVT VT =
N->getValueType(0);
9268 SDNode *BVN =
N->getOperand(0).getNode();
9273 unsigned HiElt = 1 - LoElt;
9278 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9294 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9295 SDNode *Elt =
N->getOperand(i).getNode();
9298 unsigned HalfSize = EltSize / 2;
9300 if (!
isIntN(HalfSize,
C->getSExtValue()))
9303 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9342 switch (OrigSimpleTy) {
9358 unsigned ExtOpcode) {
9381 if (ExtendedTy == LD->getMemoryVT())
9382 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9383 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9384 LD->getMemOperand()->getFlags());
9390 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9391 LD->getMemoryVT(), LD->getAlign(),
9392 LD->getMemOperand()->getFlags());
9405 N->getOperand(0)->getValueType(0),
9411 "Expected extending load");
9417 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9426 SDNode *BVN =
N->getOperand(0).getNode();
9428 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9436 EVT VT =
N->getValueType(0);
9442 for (
unsigned i = 0; i != NumElts; ++i) {
9443 const APInt &CInt =
N->getConstantOperandAPInt(i);
9452 unsigned Opcode =
N->getOpcode();
9454 SDNode *N0 =
N->getOperand(0).getNode();
9455 SDNode *N1 =
N->getOperand(1).getNode();
9463 unsigned Opcode =
N->getOpcode();
9465 SDNode *N0 =
N->getOperand(0).getNode();
9466 SDNode *N1 =
N->getOperand(1).getNode();
9476 EVT VT =
Op.getValueType();
9478 "unexpected type for custom-lowering ISD::MUL");
9479 SDNode *N0 =
Op.getOperand(0).getNode();
9480 SDNode *N1 =
Op.getOperand(1).getNode();
9481 unsigned NewOpc = 0;
9485 if (isN0SExt && isN1SExt)
9486 NewOpc = ARMISD::VMULLs;
9490 if (isN0ZExt && isN1ZExt)
9491 NewOpc = ARMISD::VMULLu;
9492 else if (isN1SExt || isN1ZExt) {
9496 NewOpc = ARMISD::VMULLs;
9499 NewOpc = ARMISD::VMULLu;
9503 NewOpc = ARMISD::VMULLu;
9509 if (VT == MVT::v2i64)
9526 "unexpected types for extended operands to VMULL");
9527 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9562 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9596 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9599 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9620 EVT VT =
Op.getValueType();
9621 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9622 "unexpected type for custom-lowering ISD::SDIV");
9629 if (VT == MVT::v8i8) {
9657 EVT VT =
Op.getValueType();
9658 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9659 "unexpected type for custom-lowering ISD::UDIV");
9666 if (VT == MVT::v8i8) {
9705 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9708 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9712 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9732 unsigned Opcode,
bool IsSigned) {
9733 EVT VT0 =
Op.getValue(0).getValueType();
9734 EVT VT1 =
Op.getValue(1).getValueType();
9736 bool InvertCarry = Opcode == ARMISD::SUBE;
9756 EVT VT =
Op.getValueType();
9757 assert((VT == MVT::i32 || VT == MVT::i64) &&
9758 "unexpected type for custom lowering DIV");
9764 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9766 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9773 for (
auto AI : {1, 0}) {
9775 Args.emplace_back(Operand,
9792ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9800 const bool MinSize =
ST.hasMinSize();
9801 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9802 :
ST.hasDivideInARMMode();
9806 if (
N->getOperand(0).getValueType().isVector())
9811 if (!(MinSize && HasDivide))
9824 if (Divisor.
sgt(128))
9832 assert(
Op.getValueType() == MVT::i32 &&
9833 "unexpected type for custom lowering DIV");
9836 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9839 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9845 if (
N->getValueType(0) == MVT::i32)
9846 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9849 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9853void ARMTargetLowering::ExpandDIV_Windows(
9858 assert(
Op.getValueType() == MVT::i64 &&
9859 "unexpected type for custom lowering DIV");
9874std::pair<SDValue, SDValue>
9875ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9881 EVT MemVT =
LD->getMemoryVT();
9882 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9886 unsigned AS =
LD->getAddressSpace();
9887 Align Alignment =
LD->getAlign();
9889 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9891 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9899 Opts, dl,
LD->getChain());
9924 EVT MemVT =
ST->getMemoryVT();
9925 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9929 unsigned AS =
ST->getAddressSpace();
9930 Align Alignment =
ST->getAlign();
9932 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9934 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9943 if (
ST->isTruncatingStore())
9948 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9949 dl,
ST->getChain());
9951 return CallResult.second;
9962 EVT MemVT = LD->getMemoryVT();
9963 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9964 MemVT == MVT::v16i1) &&
9965 "Expected a predicate type!");
9966 assert(MemVT ==
Op.getValueType());
9968 "Expected a non-extending load");
9969 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9983 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9985 LD->getMemOperand());
9991 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9992 if (MemVT != MVT::v16i1)
10001 EVT MemVT =
LD->getMemoryVT();
10003 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10004 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
10005 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10006 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10009 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
10010 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10015 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
10016 auto Pair = LowerAEABIUnalignedLoad(
SDValue(
N, 0), DAG);
10018 Results.push_back(Pair.first);
10019 Results.push_back(Pair.second);
10026 EVT MemVT = ST->getMemoryVT();
10027 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10028 MemVT == MVT::v16i1) &&
10029 "Expected a predicate type!");
10030 assert(MemVT == ST->getValue().getValueType());
10031 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10032 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10037 SDValue Build = ST->getValue();
10038 if (MemVT != MVT::v16i1) {
10051 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
10057 ST->getChain(), dl, GRP, ST->getBasePtr(),
10059 ST->getMemOperand());
10065 EVT MemVT =
ST->getMemoryVT();
10067 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10068 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
10069 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10070 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10071 SDNode *
N =
Op.getNode();
10084 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10085 MemVT,
ST->getMemOperand());
10086 }
else if (Subtarget->hasMVEIntegerOps() &&
10087 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10088 MemVT == MVT::v16i1))) {
10090 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
10091 return LowerAEABIUnalignedStore(
Op, DAG);
10098 (
N->getOpcode() == ARMISD::VMOVIMM &&
10104 MVT VT =
Op.getSimpleValueType();
10106 SDValue PassThru =
N->getPassThru();
10117 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10118 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10119 N->getExtensionType(),
N->isExpandingLoad());
10122 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
10124 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10131 if (!ST->hasMVEIntegerOps())
10135 unsigned BaseOpcode = 0;
10136 switch (
Op->getOpcode()) {
10152 unsigned NumActiveLanes = NumElts;
10154 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10155 NumActiveLanes == 2) &&
10156 "Only expected a power 2 vector size");
10160 while (NumActiveLanes > 4) {
10161 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10163 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10164 NumActiveLanes /= 2;
10168 if (NumActiveLanes == 4) {
10178 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10179 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10180 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10186 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10190 if (EltVT !=
Op->getValueType(0))
10197 if (!ST->hasMVEFloatOps())
10204 if (!ST->hasNEON())
10212 unsigned PairwiseIntrinsic = 0;
10213 switch (
Op->getOpcode()) {
10217 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10220 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10223 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10226 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10232 unsigned NumActiveLanes = NumElts;
10234 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10235 NumActiveLanes == 2) &&
10236 "Only expected a power 2 vector size");
10242 VT =
Lo.getValueType();
10244 NumActiveLanes /= 2;
10248 while (NumActiveLanes > 1) {
10250 NumActiveLanes /= 2;
10257 if (EltVT !=
Op.getValueType()) {
10258 unsigned Extend = 0;
10259 switch (
Op->getOpcode()) {
10271 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10316 const SDValue Ops[] = {RegClass, V0, SubReg0,
V1, SubReg1};
10322 SDLoc dl(V.getNode());
10323 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10333 assert(
N->getValueType(0) == MVT::i64 &&
10334 "AtomicCmpSwap on types less than 64 should be legal");
10343 ARM::CMP_SWAP_64,
SDLoc(
N),
10344 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10363 EVT VT =
Op.getValueType();
10372 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10374 Chain, IsSignaling);
10375 if (!
RHS.getNode()) {
10391 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10393 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10394 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10411 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10414 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10427 if (!IsSigned && Subtarget->isThumb1Only()) {
10445 Sub1Result, Sub1Result, Flags1);
10460 if (
Op.getValueType() != MVT::i32)
10474 unsigned Opcode = ARMISD::SUBC;
10483 bool CanUseAdd =
false;
10499 Opcode = ARMISD::ADDC;
10523 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10524 GTCondValue, Flags);
10528 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10529 LTCondValue, Flags);
10531 if (
Op.getValueType() != MVT::i32)
10539 switch (
Op.getOpcode()) {
10573 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10577 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10578 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10600 return LowerSET_FPMODE(
Op, DAG);
10602 return LowerRESET_FPMODE(
Op, DAG);
10606 !
Op.getValueType().isVector())
10607 return LowerDIV_Windows(
Op, DAG,
true);
10611 !
Op.getValueType().isVector())
10612 return LowerDIV_Windows(
Op, DAG,
false);
10628 return LowerALUO(
Op, DAG);
10636 EVT MemVT = LD->getMemoryVT();
10637 if (Subtarget->hasMVEIntegerOps() &&
10638 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10639 MemVT == MVT::v16i1))
10642 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10648 return LowerSTORE(
Op, DAG, Subtarget);
10673 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10682 return LowerSPONENTRY(
Op, DAG);
10684 return LowerFP_TO_BF16(
Op, DAG);
10685 case ARMISD::WIN__DBZCHK:
return SDValue();
10688 return LowerCMP(
Op, DAG);
10690 return LowerABS(
Op, DAG);
10695 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10696 Op.getOperand(1).getValueType() == MVT::bf16) &&
10697 "Expected custom lowering of rounding operations only for f16");
10700 {
Op.getOperand(0),
Op.getOperand(1)});
10701 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10702 {Ext.getValue(1), Ext.getValue(0)});
10709 unsigned IntNo =
N->getConstantOperandVal(0);
10711 if (IntNo == Intrinsic::arm_smlald)
10712 Opc = ARMISD::SMLALD;
10713 else if (IntNo == Intrinsic::arm_smlaldx)
10714 Opc = ARMISD::SMLALDX;
10715 else if (IntNo == Intrinsic::arm_smlsld)
10716 Opc = ARMISD::SMLSLD;
10717 else if (IntNo == Intrinsic::arm_smlsldx)
10718 Opc = ARMISD::SMLSLDX;
10724 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10728 N->getOperand(1),
N->getOperand(2),
10740 switch (
N->getOpcode()) {
10747 Res = ExpandBITCAST(
N, DAG, Subtarget);
10756 Res = LowerREM(
N, DAG);
10760 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10777 "can only expand DIV on Windows");
10789 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10818 "ROPI/RWPI not currently supported with SjLj");
10827 bool isThumb = Subtarget->isThumb();
10828 bool isThumb2 = Subtarget->
isThumb2();
10831 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10837 : &ARM::GPRRegClass;
10943 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10946 MachineRegisterInfo *MRI = &MF->
getRegInfo();
10951 : &ARM::GPRnopcRegClass;
10955 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10956 unsigned MaxCSNum = 0;
10957 for (MachineBasicBlock &BB : *MF) {
10963 for (MachineInstr &
II : BB) {
10964 if (!
II.isEHLabel())
10967 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10968 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10970 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10971 for (
unsigned Idx : CallSiteIdxs) {
10972 CallSiteNumToLPad[Idx].push_back(&BB);
10973 MaxCSNum = std::max(MaxCSNum, Idx);
10980 std::vector<MachineBasicBlock*> LPadList;
10981 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10982 LPadList.reserve(CallSiteNumToLPad.
size());
10983 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10984 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10985 for (MachineBasicBlock *
MBB : MBBList) {
10986 LPadList.push_back(
MBB);
10991 assert(!LPadList.empty() &&
10992 "No landing pad destinations for the dispatch jump table!");
10995 MachineJumpTableInfo *JTI =
11002 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
11005 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
11007 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
11010 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
11014 MF->insert(MF->end(), DispatchBB);
11015 MF->insert(MF->end(), DispContBB);
11016 MF->insert(MF->end(), TrapBB);
11020 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11022 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
11026 MachineInstrBuilder MIB;
11027 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11029 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
11039 unsigned NumLPads = LPadList.size();
11040 if (Subtarget->isThumb2()) {
11042 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11048 if (NumLPads < 256) {
11049 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11051 .
addImm(LPadList.size())
11055 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11056 .
addImm(NumLPads & 0xFFFF)
11059 unsigned VReg2 = VReg1;
11060 if ((NumLPads & 0xFFFF0000) != 0) {
11062 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11068 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11074 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11080 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11085 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11092 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11096 }
else if (Subtarget->isThumb()) {
11098 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11104 if (NumLPads < 256) {
11105 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11110 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11112 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11115 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11116 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11119 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11123 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11129 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11135 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11142 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11147 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11153 MachineMemOperand *JTMMOLd =
11158 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11164 unsigned NewVReg6 = NewVReg5;
11165 if (IsPositionIndependent) {
11167 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11174 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11179 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11185 if (NumLPads < 256) {
11186 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11190 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11192 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11193 .
addImm(NumLPads & 0xFFFF)
11196 unsigned VReg2 = VReg1;
11197 if ((NumLPads & 0xFFFF0000) != 0) {
11199 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11205 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11210 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11212 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11215 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11216 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11219 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11224 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11236 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11242 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11246 MachineMemOperand *JTMMOLd =
11250 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11257 if (IsPositionIndependent) {
11258 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11263 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11270 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11271 for (MachineBasicBlock *CurMBB : LPadList) {
11272 if (SeenMBBs.
insert(CurMBB).second)
11279 for (MachineBasicBlock *BB : InvokeBBs) {
11283 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11284 while (!Successors.empty()) {
11285 MachineBasicBlock *SMBB = Successors.pop_back_val();
11287 BB->removeSuccessor(SMBB);
11293 BB->normalizeSuccProbs();
11300 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11301 if (!
II->isCall())
continue;
11303 DenseSet<unsigned> DefRegs;
11305 OI =
II->operands_begin(), OE =
II->operands_end();
11307 if (!OI->isReg())
continue;
11308 DefRegs.
insert(OI->getReg());
11311 MachineInstrBuilder MIB(*MF, &*
II);
11313 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11314 unsigned Reg = SavedRegs[i];
11315 if (Subtarget->isThumb2() &&
11316 !ARM::tGPRRegClass.contains(
Reg) &&
11317 !ARM::hGPRRegClass.contains(
Reg))
11319 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11321 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11333 for (MachineBasicBlock *MBBLPad : MBBLPads)
11334 MBBLPad->setIsEHPad(
false);
11337 MI.eraseFromParent();
11350static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11352 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11353 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11355 return LdSize == 4 ? ARM::tLDRi
11356 : LdSize == 2 ? ARM::tLDRHi
11357 : LdSize == 1 ? ARM::tLDRBi : 0;
11359 return LdSize == 4 ? ARM::t2LDR_POST
11360 : LdSize == 2 ? ARM::t2LDRH_POST
11361 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11362 return LdSize == 4 ? ARM::LDR_POST_IMM
11363 : LdSize == 2 ? ARM::LDRH_POST
11364 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11369static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11371 return StSize == 16 ? ARM::VST1q32wb_fixed
11372 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11374 return StSize == 4 ? ARM::tSTRi
11375 : StSize == 2 ? ARM::tSTRHi
11376 : StSize == 1 ? ARM::tSTRBi : 0;
11378 return StSize == 4 ? ARM::t2STR_POST
11379 : StSize == 2 ? ARM::t2STRH_POST
11380 : StSize == 1 ? ARM::t2STRB_POST : 0;
11381 return StSize == 4 ? ARM::STR_POST_IMM
11382 : StSize == 2 ? ARM::STRH_POST
11383 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11390 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11391 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11392 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11393 assert(LdOpc != 0 &&
"Should have a load opcode");
11400 }
else if (IsThumb1) {
11406 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11411 }
else if (IsThumb2) {
11431 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11432 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11433 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11434 assert(StOpc != 0 &&
"Should have a store opcode");
11436 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11441 }
else if (IsThumb1) {
11448 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11453 }
else if (IsThumb2) {
11454 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11460 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11475 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11481 unsigned SizeVal =
MI.getOperand(2).getImm();
11482 unsigned Alignment =
MI.getOperand(3).getImm();
11486 MachineRegisterInfo &MRI = MF->
getRegInfo();
11487 unsigned UnitSize = 0;
11491 bool IsThumb1 = Subtarget->isThumb1Only();
11492 bool IsThumb2 = Subtarget->isThumb2();
11493 bool IsThumb = Subtarget->isThumb();
11495 if (Alignment & 1) {
11497 }
else if (Alignment & 2) {
11502 Subtarget->hasNEON()) {
11503 if ((Alignment % 16 == 0) && SizeVal >= 16)
11505 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11514 bool IsNeon = UnitSize >= 8;
11515 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11517 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11518 : UnitSize == 8 ? &ARM::DPRRegClass
11521 unsigned BytesLeft = SizeVal % UnitSize;
11522 unsigned LoopSize = SizeVal - BytesLeft;
11524 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11528 unsigned srcIn = src;
11529 unsigned destIn = dest;
11530 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11535 IsThumb1, IsThumb2);
11537 IsThumb1, IsThumb2);
11545 for (
unsigned i = 0; i < BytesLeft; i++) {
11550 IsThumb1, IsThumb2);
11552 IsThumb1, IsThumb2);
11556 MI.eraseFromParent();
11582 MF->
insert(It, loopMBB);
11583 MF->
insert(It, exitMBB);
11586 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11597 if (Subtarget->useMovt()) {
11598 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11601 }
else if (Subtarget->genExecuteOnly()) {
11602 assert(IsThumb &&
"Non-thumb expected to have used movt");
11607 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11611 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11612 MachineMemOperand *CPMMO =
11636 MachineBasicBlock *entryBB = BB;
11651 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11659 IsThumb1, IsThumb2);
11661 IsThumb1, IsThumb2);
11665 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11671 MachineInstrBuilder MIB =
11673 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11682 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11691 auto StartOfExit = exitMBB->
begin();
11695 unsigned srcIn = srcLoop;
11696 unsigned destIn = destLoop;
11697 for (
unsigned i = 0; i < BytesLeft; i++) {
11701 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11702 IsThumb1, IsThumb2);
11703 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11704 IsThumb1, IsThumb2);
11709 MI.eraseFromParent();
11717 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11720 assert(TM.getTargetTriple().isOSWindows() &&
11721 "__chkstk is only supported on Windows");
11722 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11742 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11743 if (ChkStkLibcall == RTLIB::Unsupported)
11747 switch (TM.getCodeModel()) {
11789 MI.eraseFromParent();
11798 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11813 .
addReg(
MI.getOperand(0).getReg())
11821 MI.eraseFromParent();
11845 if (miI == BB->
end()) {
11847 if (Succ->isLiveIn(ARM::CPSR))
11853 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11866 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11873 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11880 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11883 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11884 .
addUse(TotalIterationsReg)
11891 return TotalIterationsReg;
11902 Register TotalIterationsReg,
bool IsMemcpy) {
11911 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11921 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11929 Register RemainingLoopIterationsReg =
11931 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11932 .
addUse(TotalIterationsReg)
11934 .
addUse(RemainingLoopIterationsReg)
11940 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11941 .
addUse(ElementCountReg)
11943 .
addUse(RemainingElementsReg)
11948 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11949 .
addUse(PredCounterPhiReg)
11954 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11955 .
addUse(PredCounterPhiReg)
11964 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11973 SrcValueReg = OpSrcReg;
11975 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11986 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11987 .
addUse(LoopCounterPhiReg)
11990 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11991 .
addUse(RemainingLoopIterationsReg)
12009 "Invalid call instruction for a KCFI check");
12012 switch (
MBBI->getOpcode()) {
12015 case ARM::BLX_pred:
12016 case ARM::BLX_noip:
12017 case ARM::BLX_pred_noip:
12019 TargetOp = &
MBBI->getOperand(0);
12021 case ARM::TCRETURNri:
12022 case ARM::TCRETURNrinotr12:
12023 case ARM::TAILJMPr:
12024 case ARM::TAILJMPr4:
12025 TargetOp = &
MBBI->getOperand(0);
12031 case ARM::tBLXr_noip:
12032 case ARM::tBX_CALL:
12033 TargetOp = &
MBBI->getOperand(2);
12036 case ARM::tTAILJMPr:
12037 TargetOp = &
MBBI->getOperand(0);
12043 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
12047 unsigned KCFICheckOpcode;
12048 if (Subtarget->isThumb()) {
12049 if (Subtarget->isThumb2()) {
12050 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
12052 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
12055 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
12069 bool isThumb2 = Subtarget->isThumb2();
12070 switch (
MI.getOpcode()) {
12077 case ARM::tLDR_postidx: {
12081 .
add(
MI.getOperand(2))
12082 .
add(
MI.getOperand(3))
12083 .
add(
MI.getOperand(4))
12084 .
add(
MI.getOperand(0))
12086 MI.eraseFromParent();
12090 case ARM::MVE_MEMCPYLOOPINST:
12091 case ARM::MVE_MEMSETLOOPINST: {
12121 Register OpDestReg =
MI.getOperand(0).getReg();
12122 Register OpSrcReg =
MI.getOperand(1).getReg();
12123 Register OpSizeReg =
MI.getOperand(2).getReg();
12143 if (TpExit == BB) {
12145 "block containing memcpy/memset Pseudo");
12155 genTPEntry(TpEntry, TpLoopBody, TpExit, OpSizeReg,
TII, dl, MRI);
12158 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12160 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12163 Properties.resetNoPHIs();
12175 MI.eraseFromParent();
12185 case ARM::t2STR_preidx:
12186 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12188 case ARM::t2STRB_preidx:
12189 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12191 case ARM::t2STRH_preidx:
12192 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12195 case ARM::STRi_preidx:
12196 case ARM::STRBi_preidx: {
12197 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12198 : ARM::STRB_PRE_IMM;
12200 unsigned Offset =
MI.getOperand(4).getImm();
12208 .
add(
MI.getOperand(0))
12209 .
add(
MI.getOperand(1))
12210 .
add(
MI.getOperand(2))
12212 .
add(
MI.getOperand(5))
12213 .
add(
MI.getOperand(6))
12215 MI.eraseFromParent();
12218 case ARM::STRr_preidx:
12219 case ARM::STRBr_preidx:
12220 case ARM::STRH_preidx: {
12222 switch (
MI.getOpcode()) {
12224 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12225 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12226 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12231 MI.eraseFromParent();
12235 case ARM::tMOVCCr_pseudo: {
12253 F->insert(It, copy0MBB);
12254 F->insert(It, sinkMBB);
12257 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12263 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12279 .
addImm(
MI.getOperand(3).getImm())
12280 .
addReg(
MI.getOperand(4).getReg());
12295 .
addReg(
MI.getOperand(1).getReg())
12297 .
addReg(
MI.getOperand(2).getReg())
12300 MI.eraseFromParent();
12305 case ARM::BCCZi64: {
12311 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12316 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12320 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12326 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12330 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12340 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12349 MI.eraseFromParent();
12353 case ARM::Int_eh_sjlj_setjmp:
12354 case ARM::Int_eh_sjlj_setjmp_nofp:
12355 case ARM::tInt_eh_sjlj_setjmp:
12356 case ARM::t2Int_eh_sjlj_setjmp:
12357 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12360 case ARM::Int_eh_sjlj_setup_dispatch:
12361 EmitSjLjDispatchBlock(
MI, BB);
12363 case ARM::COPY_STRUCT_BYVAL_I32:
12365 return EmitStructByval(
MI, BB);
12366 case ARM::WIN__CHKSTK:
12367 return EmitLowered__chkstk(
MI, BB);
12368 case ARM::WIN__DBZCHK:
12369 return EmitLowered__dbzchk(
MI, BB);
12385 if (!
Node->hasAnyUseOfValue(0)) {
12386 MI.getOperand(0).setIsDead(
true);
12388 if (!
Node->hasAnyUseOfValue(1)) {
12389 MI.getOperand(1).setIsDead(
true);
12393 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12395 : &ARM::GPRRegClass);
12402 if (
MI.getOpcode() == ARM::MEMCPY) {
12423 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12424 &&
"converted opcode should be the same except for cc_out"
12425 " (and, on Thumb1, pred)");
12433 if (Subtarget->isThumb1Only()) {
12434 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12435 MI.addOperand(
MI.getOperand(1));
12436 MI.removeOperand(1);
12440 for (
unsigned i =
MI.getNumOperands(); i--;) {
12442 if (
op.isReg() &&
op.isUse()) {
12445 MI.tieOperands(DefIdx, i);
12453 ccOutIdx =
MCID->getNumOperands() - 1;
12455 ccOutIdx =
MCID->getNumOperands() - 1;
12459 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12460 assert(!NewOpc &&
"Optional cc_out operand required");
12465 bool definesCPSR =
false;
12466 bool deadCPSR =
false;
12467 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12471 definesCPSR =
true;
12474 MI.removeOperand(i);
12478 if (!definesCPSR) {
12479 assert(!NewOpc &&
"Optional cc_out operand required");
12482 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12484 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12485 "expect uninitialized optional cc_out operand");
12487 if (!Subtarget->isThumb1Only())
12523 switch (
N->getOpcode()) {
12524 default:
return false;
12526 CC =
N->getOperand(0);
12548 EVT VT =
N->getValueType(0);
12549 CC =
N->getOperand(0);
12596 EVT VT =
N->getValueType(0);
12599 bool SwapSelectOps;
12601 NonConstantVal, DAG))
12607 OtherOp, NonConstantVal);
12613 CCOp, TrueVal, FalseVal);
12633 if (
N->getOpcode() == ARMISD::VUZP)
12637 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12652 if (!
N->getValueType(0).is64BitVector())
12660 EVT VT =
N->getValueType(0);
12699 EVT VT =
N->getValueType(0);
12705 Opcode = Intrinsic::arm_neon_vpaddls;
12707 Opcode = Intrinsic::arm_neon_vpaddlu;
12735 EVT VT =
N->getValueType(0);
12750 unsigned nextIndex = 0;
12801 Ops.push_back(Vec);
12818 return DAG.
getNode(ExtOp, dl, VT, tmp);
12849 if (SRA.getOpcode() !=
ISD::SRA) {
12856 if (Const->getZExtValue() != 31)
12861 if (SRA.getOperand(0) !=
Mul)
12865 SDLoc dl(AddcNode);
12866 unsigned Opcode = 0;
12871 Opcode = ARMISD::SMLALBB;
12872 Op0 =
Mul.getOperand(0);
12873 Op1 =
Mul.getOperand(1);
12875 Opcode = ARMISD::SMLALBT;
12876 Op0 =
Mul.getOperand(0);
12877 Op1 =
Mul.getOperand(1).getOperand(0);
12879 Opcode = ARMISD::SMLALTB;
12880 Op0 =
Mul.getOperand(0).getOperand(0);
12881 Op1 =
Mul.getOperand(1);
12883 Opcode = ARMISD::SMLALTT;
12884 Op0 =
Mul->getOperand(0).getOperand(0);
12885 Op1 =
Mul->getOperand(1).getOperand(0);
12901 SDValue resNode(AddcNode, 0);
12929 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12930 "Expect an ADDE or SUBE");
12934 "ADDE node has the wrong inputs");
12938 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12939 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12940 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12941 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12953 "Expect ADDC with two result values. First: i32");
12957 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12973 bool IsLeftOperandMUL =
false;
12978 IsLeftOperandMUL =
true;
12989 SDValue *LowAddSub =
nullptr;
12992 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12995 if (IsLeftOperandMUL)
12996 HiAddSub = &AddeSubeOp1;
12998 HiAddSub = &AddeSubeOp0;
13003 if (AddcSubcOp0 == MULOp.
getValue(0)) {
13004 LoMul = &AddcSubcOp0;
13005 LowAddSub = &AddcSubcOp1;
13007 if (AddcSubcOp1 == MULOp.
getValue(0)) {
13008 LoMul = &AddcSubcOp1;
13009 LowAddSub = &AddcSubcOp0;
13017 if (AddcSubcNode == HiAddSub->getNode() ||
13033 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13038 Ops.push_back(*HiAddSub);
13039 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
13040 FinalOpc = ARMISD::SMMLSR;
13042 FinalOpc = ARMISD::SMMLAR;
13047 return SDValue(AddeSubeNode, 0);
13048 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
13054 Ops.push_back(*LowAddSub);
13055 Ops.push_back(*HiAddSub);
13068 return SDValue(AddeSubeNode, 0);
13080 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13085 if (AddcNode->
getOpcode() != ARMISD::ADDC)
13089 SDNode *UmlalNode =
nullptr;
13128 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13133 SDNode* AddcNode =
N->getOperand(2).getNode();
13134 SDNode* AddeNode =
N->getOperand(3).getNode();
13135 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
13136 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
13142 {N->getOperand(0), N->getOperand(1),
13143 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13153 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13157 if (
LHS->getOpcode() == ARMISD::ADDE &&
13167 int32_t imm =
C->getSExtValue();
13168 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13171 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13173 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13188 int64_t imm =
C->getSExtValue();
13197 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13199 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13200 N->getOperand(0),
RHS,
N->getOperand(2));
13212 if (!Subtarget->hasMVEIntegerOps())
13225 SetCC =
N->getOperand(0);
13229 TrueVal =
N->getOperand(1);
13230 FalseVal =
N->getOperand(2);
13232 LHS =
N->getOperand(0);
13233 RHS =
N->getOperand(1);
13235 TrueVal =
N->getOperand(2);
13236 FalseVal =
N->getOperand(3);
13241 unsigned int Opcode = 0;
13245 Opcode = ARMISD::VMINVu;
13251 Opcode = ARMISD::VMINVs;
13257 Opcode = ARMISD::VMAXVu;
13263 Opcode = ARMISD::VMAXVs;
13270 switch (TrueVal->getOpcode()) {
13289 if (TrueVal !=
LHS || FalseVal !=
RHS)
13292 EVT LeftType =
LHS->getValueType(0);
13293 EVT RightType =
RHS->getValueType(0);
13296 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13300 if (VectorScalarType != MVT::i32)
13308 if (VectorScalarType != MVT::i32)
13321 EVT VT =
N->getValueType(0);
13329 Shft =
N->getOperand(0);
13336 Cmp.getOperand(0) !=
N->getOperand(1) ||
13337 Cmp.getOperand(1) !=
N->getOperand(2))
13339 Shft =
N->getOperand(1);
13351 ScalarType = MVT::i8;
13354 case (1 << 15) - 1:
13355 ScalarType = MVT::i16;
13358 case (1ULL << 31) - 1:
13359 ScalarType = MVT::i32;
13390 unsigned LegalLanes = 128 / (ShftAmt + 1);
13402 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13403 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13404 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13405 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13414 for (
unsigned I = 0;
I < NumParts; ++
I) {
13421 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13431 if (!Subtarget->hasMVEIntegerOps())
13436 if (
N->getOperand(0).getOpcode() == ARMISD::PREDICATE_CAST &&
13438 unsigned C =
N->getOperand(0).getConstantOperandVal(0);
13440 return N->getOperand(2);
13442 return N->getOperand(1);
13457 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13467 if (!Const || !Const->isOne())
13485 EVT VT =
N->getValueType(0);
13487 if (!Subtarget->hasMVEIntegerOps() ||
13516 Opc = Intrinsic::arm_mve_vctp64;
13519 Opc = Intrinsic::arm_mve_vctp32;
13522 Opc = Intrinsic::arm_mve_vctp16;
13525 Opc = Intrinsic::arm_mve_vctp8;
13579 EVT VT =
N->getValueType(0);
13585 switch (
Op.getOpcode()) {
13587 case ARMISD::VADDVs:
13588 case ARMISD::VADDVu:
13589 case ARMISD::VMLAVs:
13590 case ARMISD::VMLAVu:
13610 unsigned N0RedOp = 0;
13617 unsigned N1RedOp = 0;
13631 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13633 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13640 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13664 if (!BaseLocDecomp0.getBase() ||
13665 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13666 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13668 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13670 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13680 if (IsBefore < 0) {
13683 }
else if (IsBefore > 0) {
13696 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13706 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13716 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13718 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13725 if (!Subtarget->hasMVEIntegerOps())
13731 EVT VT =
N->getValueType(0);
13736 if (VT != MVT::i64)
13747 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13767 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13776 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13778 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13780 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13782 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13784 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13786 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13788 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13790 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13792 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13794 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13796 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13798 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13800 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13802 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13804 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13806 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13816 "Expected shift op");
13818 SDValue ShiftLHS =
N->getOperand(0);
13832 if (Subtarget->isThumb1Only()) {
13843 if (Const->getAPIntValue().ult(256))
13846 Const->getAPIntValue().sgt(-256))
13862 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13863 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13864 "Expected XOR(SHIFT) pattern");
13869 if (XorC && ShiftC) {
13870 unsigned MaskIdx, MaskLen;
13871 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13872 unsigned ShiftAmt = ShiftC->getZExtValue();
13873 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13874 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13875 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13876 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13886 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13888 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13889 "Expected shift-shift mask");
13891 if (!Subtarget->isThumb1Only())
13894 EVT VT =
N->getValueType(0);
13902 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13904 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13909 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps()) {
13910 if (Subtarget->isThumb1Only())
13924 return Subtarget->hasVFP2Base();
13926 return Subtarget->hasVFP2Base();
13928 return Subtarget->hasFP64();
13931 return Subtarget->hasMVEFloatOps();
13960 if (ST->isThumb1Only())
13964 for (
auto *U :
N->users()) {
13965 switch(U->getOpcode()) {
13983 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13984 U->getOperand(1).getOpcode() ==
ISD::SHL)
13994 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
14001 if (!C1ShlC2 || !C2)
14004 APInt C2Int = C2->getAPIntValue();
14005 APInt C1Int = C1ShlC2->getAPIntValue();
14007 if (C2Int.
uge(C2Width))
14013 if ((C1Int & Mask) != C1Int)
14020 auto LargeImm = [](
const APInt &Imm) {
14021 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
14022 return Imm.getBitWidth() - Zeros > 8;
14025 if (LargeImm(C1Int) || LargeImm(C2Int))
14037 SHL.dump();
N->dump());
14098 if (
Op.hasOneUse() && ShiftAmt &&
14099 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
14157 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14178 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14199 if (!Subtarget->hasVMLxForwarding())
14218 EVT VT =
N->getValueType(0);
14229 EVT VT =
N->getValueType(0);
14230 if (VT != MVT::v2i64)
14241 return Op->getOperand(0);
14255 And =
And->getOperand(0);
14260 Mask = Mask->getOperand(0);
14263 Mask.getValueType() != MVT::v4i32)
14269 return And->getOperand(0);
14274 if (
SDValue Op0 = IsSignExt(N0)) {
14275 if (
SDValue Op1 = IsSignExt(N1)) {
14276 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14277 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14278 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14281 if (
SDValue Op0 = IsZeroExt(N0)) {
14282 if (
SDValue Op1 = IsZeroExt(N1)) {
14283 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14284 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14285 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14297 EVT VT =
N->getValueType(0);
14298 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14309 if (VT != MVT::i32)
14316 int64_t MulAmt =
C->getSExtValue();
14319 ShiftAmt = ShiftAmt & (32 - 1);
14324 MulAmt >>= ShiftAmt;
14385 if (
N->getValueType(0) != MVT::i32)
14394 if (C1 == 255 || C1 == 65535)
14397 SDNode *N0 =
N->getOperand(0).getNode();
14411 if (!C2 || C2 >= 32)
14455 if (Trailing == C2 && C2 + C3 < 32) {
14468 if (Leading == C2 && C2 + C3 < 32) {
14496 EVT VT =
N->getValueType(0);
14500 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14503 APInt SplatBits, SplatUndef;
14504 unsigned SplatBitSize;
14506 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14507 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14508 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14509 SplatBitSize == 64) {
14516 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14518 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14543 if (!Subtarget->hasV6Ops() ||
14544 (Subtarget->isThumb() &&
14545 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14548 SDValue SRL = OR->getOperand(0);
14549 SDValue SHL = OR->getOperand(1);
14552 SRL = OR->getOperand(1);
14553 SHL = OR->getOperand(0);
14560 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14564 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14565 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14566 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14585 unsigned Opcode = 0;
14586 if (
isS16(OpS16, DAG))
14587 Opcode = ARMISD::SMULWB;
14589 Opcode = ARMISD::SMULWT;
14604 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14607 EVT VT =
N->getValueType(0);
14622 if (VT != MVT::i32)
14635 if (Mask == 0xffff)
14642 if ((Val & ~Mask) != Val)
14648 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14667 (Mask == ~Mask2)) {
14670 if (Subtarget->hasDSP() &&
14671 (Mask == 0xffff || Mask == 0xffff0000))
14677 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14684 (~Mask == Mask2)) {
14687 if (Subtarget->hasDSP() &&
14688 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14744 if (
N->getOpcode() == ARMISD::VCMP)
14746 else if (
N->getOpcode() == ARMISD::VCMPZ)
14754 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14761 EVT VT =
N->getValueType(0);
14766 auto IsFreelyInvertable = [&](
SDValue V) {
14767 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14773 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14791 if (AndOp.getOpcode() !=
ISD::AND)
14795 SDValue Mask = AndOp.getOperand(1);
14805 bool IsShiftRight =
false;
14808 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14809 IsShiftRight =
true;
14812 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14820 APInt RequiredMask = IsShiftRight
14823 if (MaskBits != RequiredMask)
14826 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14836 EVT VT =
N->getValueType(0);
14842 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14843 VT == MVT::v8i1 || VT == MVT::v16i1))
14846 APInt SplatBits, SplatUndef;
14847 unsigned SplatBitSize;
14849 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14850 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14851 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14852 SplatBitSize == 64) {
14859 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14861 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14881 (Subtarget->hasMVEIntegerOps() &&
14882 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14885 return ShiftInsert;
14889 return ShiftInsert;
14903 unsigned SplatBitSize;
14906 APInt SplatBits0, SplatBits1;
14910 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14911 HasAnyUndefs) && !HasAnyUndefs) {
14912 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14913 HasAnyUndefs) && !HasAnyUndefs) {
14918 SplatBits0 == ~SplatBits1) {
14926 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14946 if (CSINC.
getOpcode() != ARMISD::CSINC)
14948 if (CSINC.
getOpcode() == ARMISD::CSINC &&
14961 EVT VT =
N->getValueType(0);
14976 if (Subtarget->hasMVEIntegerOps()) {
15004 assert(
N->getOpcode() == ARMISD::BFI);
15007 ToMask =
~N->getConstantOperandAPInt(2);
15027 unsigned LastActiveBitInA =
A.countr_zero();
15028 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
15029 return LastActiveBitInA - 1 == FirstActiveBitInB;
15034 APInt ToMask, FromMask;
15039 if (V.getOpcode() != ARMISD::BFI)
15042 APInt NewToMask, NewFromMask;
15044 if (NewFrom != From)
15048 if ((NewToMask & ToMask).getBoolValue())
15073 unsigned InvMask =
N->getConstantOperandVal(2);
15077 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
15078 "undefined behavior");
15079 unsigned Mask = (1u << Width) - 1;
15081 if ((Mask & (~Mask2)) == 0)
15083 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
15090 APInt ToMask1, FromMask1;
15093 APInt ToMask2, FromMask2;
15099 APInt NewFromMask = FromMask1 | FromMask2;
15100 APInt NewToMask = ToMask1 | ToMask2;
15102 EVT VT =
N->getValueType(0);
15105 if (NewFromMask[0] == 0)
15108 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
15116 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
15117 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
15118 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
15120 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
15124 EVT VT =
N->getValueType(0);
15127 N->getOperand(1),
N->getOperand(2));
15139 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
15141 SDValue CSInc = Cmp->getOperand(0);
15151 if (CSInc.
getOpcode() == ARMISD::CSINC &&
15191 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15192 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15195 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15197 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15210 SDValue InDouble =
N->getOperand(0);
15211 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15225 SDValue BasePtr = LD->getBasePtr();
15227 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15228 LD->getAlign(), LD->getMemOperand()->getFlags());
15234 LD->getPointerInfo().getWithOffset(4),
15236 LD->getMemOperand()->getFlags());
15255 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15269 if (!Subtarget->
isLittle() && BVSwap)
15287 if (!Subtarget->
isLittle() && BVSwap)
15306 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15319 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15332 if (Copy.getValueType() == MVT::f32 &&
15334 bool HasGlue = Copy->getNumOperands() == 3;
15335 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15336 HasGlue ? Copy->getOperand(2) :
SDValue()};
15337 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15356 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15357 LN0->getMemoryVT() == MVT::i16) {
15360 LN0->getBasePtr(), LN0->getMemOperand());
15378 EVT VT =
N->getValueType(0);
15412 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15413 for (
unsigned i = 0; i < NumElts; ++i) {
15414 SDNode *Elt =
N->getOperand(i).getNode();
15431 if (
N->getNumOperands() == 2)
15437 EVT VT =
N->getValueType(0);
15443 for (
unsigned i = 0; i < NumElts; ++i) {
15469 EVT VT =
N->getValueType(0);
15477 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15482 Use->getValueType(0).isFloatingPoint())
15490 unsigned NumOfBitCastedElts = 0;
15492 unsigned NumOfRelevantElts = NumElts;
15493 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15498 ++NumOfBitCastedElts;
15502 --NumOfRelevantElts;
15506 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15524 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15529 V->getOperand(0).getValueType() == MVT::i32)
15531 V = V.getOperand(0);
15548 EVT VT =
N->getValueType(0);
15553 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15555 if (
Op->getOperand(0).getValueType() == VT)
15556 return Op->getOperand(0);
15557 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15564 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15571 if (
Op.getValueType() == MVT::i32) {
15582 EVT VT =
N->getValueType(0);
15587 if (ST->isLittle())
15591 if (
Op.getValueType() == VT)
15598 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15600 if (
Op->getOperand(0).getValueType() == VT)
15601 return Op->getOperand(0);
15602 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15610 if (!Subtarget->hasMVEIntegerOps())
15613 EVT VT =
N->getValueType(0);
15621 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15627 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15631 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15644 EVT VT =
N->getValueType(0);
15645 SDNode *Elt =
N->getOperand(1).getNode();
15660 Vec, V,
N->getOperand(2));
15670 EVT VT =
N->getValueType(0);
15698 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15699 isa<ConstantSDNode>(V->getOperand(1)) &&
15700 V->getConstantOperandVal(1) == Lane + 1 &&
15701 V->getOperand(0).getResNo() == ResNo;
15703 if (OtherIt == Op0->
users().
end())
15708 SDValue OtherExt(*OtherIt, 0);
15720 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15723 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15733 EVT VT =
N->getValueType(0);
15737 if (Op0->
getOpcode() == ARMISD::VDUP) {
15739 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15740 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15741 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15742 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15743 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15746 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15747 X =
X->getOperand(0);
15748 if (
X.getValueType() == VT)
15756 return Op0.
getOperand(
N->getConstantOperandVal(1));
15766 unsigned Offset =
N->getConstantOperandVal(1);
15768 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15778 unsigned Idx =
N->getConstantOperandVal(1);
15793 unsigned Lane =
N->getConstantOperandVal(1);
15821 EVT VT =
N->getValueType(0);
15824 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15826 Op.getOperand(0).getValueType().getScalarType())
15827 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15836 SDValue SubVec =
N->getOperand(1);
15837 uint64_t IdxVal =
N->getConstantOperandVal(2);
15848 if (IdxVal == 0 && Vec.
isUndef())
15854 (IdxVal != 0 && IdxVal != NumSubElts))
15885 ARMISD::VMOVN,
DL, VT,
15891 ARMISD::VMOVN,
DL, VT,
15927 EVT VT =
N->getValueType(0);
15938 unsigned HalfElts = NumElts/2;
15940 for (
unsigned n = 0; n < NumElts; ++n) {
15943 if (MaskElt < (
int)HalfElts)
15945 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15946 NewElt = HalfElts + MaskElt - NumElts;
15989 bool SimpleConstIncOnly,
15997 bool isLoadOp =
true;
15998 bool isLaneOp =
false;
16001 bool hasAlignment =
true;
16002 unsigned NewOpc = 0;
16003 unsigned NumVecs = 0;
16004 if (
Target.isIntrinsic) {
16005 unsigned IntNo =
N->getConstantOperandVal(1);
16009 case Intrinsic::arm_neon_vld1:
16013 case Intrinsic::arm_neon_vld2:
16017 case Intrinsic::arm_neon_vld3:
16021 case Intrinsic::arm_neon_vld4:
16025 case Intrinsic::arm_neon_vld1x2:
16028 hasAlignment =
false;
16030 case Intrinsic::arm_neon_vld1x3:
16033 hasAlignment =
false;
16035 case Intrinsic::arm_neon_vld1x4:
16038 hasAlignment =
false;
16040 case Intrinsic::arm_neon_vld2dup:
16044 case Intrinsic::arm_neon_vld3dup:
16048 case Intrinsic::arm_neon_vld4dup:
16052 case Intrinsic::arm_neon_vld2lane:
16057 case Intrinsic::arm_neon_vld3lane:
16062 case Intrinsic::arm_neon_vld4lane:
16067 case Intrinsic::arm_neon_vst1:
16072 case Intrinsic::arm_neon_vst2:
16073 NewOpc = ARMISD::VST2_UPD;
16077 case Intrinsic::arm_neon_vst3:
16082 case Intrinsic::arm_neon_vst4:
16083 NewOpc = ARMISD::VST4_UPD;
16087 case Intrinsic::arm_neon_vst2lane:
16093 case Intrinsic::arm_neon_vst3lane:
16099 case Intrinsic::arm_neon_vst4lane:
16105 case Intrinsic::arm_neon_vst1x2:
16109 hasAlignment =
false;
16111 case Intrinsic::arm_neon_vst1x3:
16115 hasAlignment =
false;
16117 case Intrinsic::arm_neon_vst1x4:
16121 hasAlignment =
false;
16126 switch (
N->getOpcode()) {
16162 VecTy =
N->getValueType(0);
16163 }
else if (
Target.isIntrinsic) {
16164 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16167 "Node has to be a load, a store, or an intrinsic!");
16168 VecTy =
N->getOperand(1).getValueType();
16176 if (isLaneOp || isVLDDUPOp)
16179 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16185 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16194 EVT AlignedVecTy = VecTy;
16214 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16215 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16226 Alignment =
Align(1);
16232 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16234 for (n = 0; n < NumResultVecs; ++n)
16235 Tys[n] = AlignedVecTy;
16236 Tys[n++] = MVT::i32;
16237 Tys[n] = MVT::Other;
16242 Ops.push_back(
N->getOperand(0));
16243 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16248 Ops.push_back(StN->getValue());
16252 unsigned LastOperand =
16253 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16254 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16255 Ops.push_back(
N->getOperand(i));
16263 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16274 for (
unsigned i = 0; i < NumResultVecs; ++i)
16279 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16280 SDValue &LdVal = NewResults[0];
16316 switch (
N->getOpcode()) {
16320 *Ptr =
N->getOperand(0);
16321 *CInc =
N->getOperand(1);
16328 *Ptr =
N->getOperand(1);
16329 *CInc =
N->getOperand(2);
16356 SDValue Addr =
N->getOperand(AddrOpIdx);
16367 unsigned ConstInc =
16372 if (BaseUpdates.
size() >= MaxBaseUpdates)
16393 unsigned UserOffset =
16396 if (!UserOffset || UserOffset <=
Offset)
16399 unsigned NewConstInc = UserOffset -
Offset;
16402 if (BaseUpdates.
size() >= MaxBaseUpdates)
16410 unsigned NumValidUpd = BaseUpdates.
size();
16411 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16422 return LHS.ConstInc <
RHS.ConstInc;
16451 unsigned IntNo =
N->getConstantOperandVal(1);
16452 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16454 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16477 bool isLoadOp =
true;
16478 unsigned NewOpc = 0;
16479 unsigned NumVecs = 0;
16483 case Intrinsic::arm_mve_vld2q:
16487 case Intrinsic::arm_mve_vld4q:
16491 case Intrinsic::arm_mve_vst2q:
16492 NewOpc = ARMISD::VST2_UPD;
16496 case Intrinsic::arm_mve_vst4q:
16497 NewOpc = ARMISD::VST4_UPD;
16506 VecTy =
N->getValueType(0);
16508 VecTy =
N->getOperand(3).getValueType();
16522 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16524 for (n = 0; n < NumResultVecs; ++n)
16526 Tys[n++] = MVT::i32;
16527 Tys[n] = MVT::Other;
16532 Ops.push_back(
N->getOperand(0));
16533 Ops.push_back(
N->getOperand(2));
16534 Ops.push_back(Inc);
16536 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16537 Ops.push_back(
N->getOperand(i));
16544 for (
unsigned i = 0; i < NumResultVecs; ++i)
16563 EVT VT =
N->getValueType(0);
16569 SDNode *VLD =
N->getOperand(0).getNode();
16572 unsigned NumVecs = 0;
16573 unsigned NewOpc = 0;
16575 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16578 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16581 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16593 if (
Use.getResNo() == NumVecs)
16596 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16597 VLDLaneNo !=
User->getConstantOperandVal(1))
16604 for (n = 0; n < NumVecs; ++n)
16606 Tys[n] = MVT::Other;
16616 unsigned ResNo =
Use.getResNo();
16618 if (ResNo == NumVecs)
16625 std::vector<SDValue> VLDDupResults;
16626 for (
unsigned n = 0; n < NumVecs; ++n)
16640 EVT VT =
N->getValueType(0);
16643 if (Subtarget->hasMVEIntegerOps()) {
16647 ExtractVT = MVT::i32;
16649 N->getOperand(0),
N->getOperand(1));
16661 Op =
Op.getOperand(0);
16662 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16666 unsigned EltSize =
Op.getScalarValueSizeInBits();
16668 unsigned Imm =
Op.getConstantOperandVal(0);
16684 if (Subtarget->hasMVEIntegerOps()) {
16687 if (
Op.getValueType() == MVT::f32)
16688 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16690 else if (
Op.getValueType() == MVT::f16)
16691 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16692 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16695 if (!Subtarget->hasNEON())
16702 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16703 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16704 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16709 LD->getMemoryVT(), LD->getMemOperand());
16720 EVT VT =
N->getValueType(0);
16742 assert(StVT != VT &&
"Cannot truncate to the same type");
16752 if (0 != (NumElems * FromEltSz) % ToEltSz)
16755 unsigned SizeRatio = FromEltSz / ToEltSz;
16760 NumElems * SizeRatio);
16766 for (
unsigned i = 0; i < NumElems; ++i)
16780 MVT StoreType = MVT::i8;
16782 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16802 for (
unsigned I = 0;
I <
E;
I++) {
16833 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16836 unsigned NumElements = 4;
16853 unsigned Off0 = Rev ? NumElts : 0;
16854 unsigned Off1 = Rev ? 0 : NumElts;
16856 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16857 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16859 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16867 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16887 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16898 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16902 NewToVT, Alignment, MMOFlags, AAInfo);
16935 unsigned NewOffset =
16943 NewToVT, Alignment, MMOFlags, AAInfo);
16965 {Extract.getOperand(0), Extract.getOperand(1)});
16996 if (Subtarget->hasNEON())
17000 if (Subtarget->hasMVEFloatOps())
17004 if (Subtarget->hasMVEIntegerOps()) {
17078 if (!Subtarget->hasNEON())
17082 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
17090 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
17092 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
17093 uint32_t IntBits = IntTy.getSizeInBits();
17094 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17095 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17106 if (
C == -1 ||
C == 0 ||
C > 32)
17111 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
17112 Intrinsic::arm_neon_vcvtfp2fxu;
17115 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
17118 if (IntBits < FloatBits)
17126 if (!Subtarget->hasMVEFloatOps())
17134 EVT VT =
N->getValueType(0);
17139 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
17141 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
17143 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
17144 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
17146 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17159 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17170 EVT VT =
N->getValueType(0);
17173 if (!
N->getFlags().hasAllowReassociation())
17180 unsigned Opc =
A.getConstantOperandVal(0);
17181 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17186 A.getOperand(3),
A.getOperand(4));
17218 if (!Subtarget->hasNEON())
17222 unsigned OpOpcode =
Op.getNode()->getOpcode();
17223 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17227 SDValue ConstVec =
N->getOperand(1);
17231 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17233 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17234 uint32_t IntBits = IntTy.getSizeInBits();
17235 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17236 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17256 int32_t
C = IntVal.exactLogBase2();
17257 if (
C == -1 ||
C == 0 ||
C > 32)
17263 if (IntBits < FloatBits)
17265 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17267 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17268 : Intrinsic::arm_neon_vcvtfxu2fp;
17276 if (!ST->hasMVEIntegerOps())
17280 EVT ResVT =
N->getValueType(0);
17308 EVT AVT =
A.getValueType();
17314 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17315 EVT AVT =
A.getValueType();
17325 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17326 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17329 if (ExtTypeMatches(
A, ExtTypes))
17330 return ExtendIfNeeded(
A, ExtendCode);
17333 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17343 if (ExtTypeMatches(
A, ExtTypes))
17344 return ExtendIfNeeded(
A, ExtendCode);
17347 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17357 if (ResVT != RetTy)
17360 if (
Mul->getOpcode() == ExtendCode &&
17361 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17363 Mul =
Mul->getOperand(0);
17372 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17373 A = ExtendIfNeeded(
A, ExtendCode);
17374 B = ExtendIfNeeded(
B, ExtendCode);
17379 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17392 if (
Mul->getOpcode() == ExtendCode &&
17393 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17395 Mul =
Mul->getOperand(0);
17404 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17405 A = ExtendIfNeeded(
A, ExtendCode);
17406 B = ExtendIfNeeded(
B, ExtendCode);
17417 EVT VT =
Ops[0].getValueType();
17418 if (VT == MVT::v16i8) {
17419 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17420 "Unexpected illegal long reduction opcode");
17421 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17433 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17446 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17448 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17449 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17451 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17452 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17454 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17457 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17460 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17464 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17467 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17470 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17473 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17476 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17479 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17482 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17484 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17486 return Create64bitNode(ARMISD::VADDLVs, {
A});
17488 return Create64bitNode(ARMISD::VADDLVu, {
A});
17491 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17494 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17497 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17499 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17501 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17503 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17506 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17509 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17516 Op =
Op->getOperand(1);
17518 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17520 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17537 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17539 if (!Shuf || !Shuf->getOperand(1).isUndef())
17544 APInt SetElts(Mask.size(), 0);
17545 for (
int E : Mask) {
17553 if (
N->getNumOperands() != VecOp + 1) {
17555 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17561 if (
Op.getValueType().isVector())
17562 Ops.push_back(
Op.getOperand(0));
17573 unsigned IsTop =
N->getConstantOperandVal(2);
17580 if (Op0->
isUndef() && !IsTop)
17585 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17586 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17594 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17596 APInt Op0DemandedElts =
17597 IsTop ? Op1DemandedElts
17612 unsigned IsTop =
N->getConstantOperandVal(2);
17614 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17615 APInt Op0DemandedElts =
17627 EVT VT =
N->getValueType(0);
17634 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17635 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17639 LHS.getOperand(0),
RHS.getOperand(0));
17654 int ShiftAmt =
C->getSExtValue();
17655 if (ShiftAmt == 0) {
17661 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17662 unsigned NewOpcode =
17663 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17678 unsigned IntNo =
N->getConstantOperandVal(0);
17689 case Intrinsic::arm_neon_vshifts:
17690 case Intrinsic::arm_neon_vshiftu:
17691 case Intrinsic::arm_neon_vrshifts:
17692 case Intrinsic::arm_neon_vrshiftu:
17693 case Intrinsic::arm_neon_vrshiftn:
17694 case Intrinsic::arm_neon_vqshifts:
17695 case Intrinsic::arm_neon_vqshiftu:
17696 case Intrinsic::arm_neon_vqshiftsu:
17697 case Intrinsic::arm_neon_vqshiftns:
17698 case Intrinsic::arm_neon_vqshiftnu:
17699 case Intrinsic::arm_neon_vqshiftnsu:
17700 case Intrinsic::arm_neon_vqrshiftns:
17701 case Intrinsic::arm_neon_vqrshiftnu:
17702 case Intrinsic::arm_neon_vqrshiftnsu: {
17703 EVT VT =
N->getOperand(1).getValueType();
17705 unsigned VShiftOpc = 0;
17708 case Intrinsic::arm_neon_vshifts:
17709 case Intrinsic::arm_neon_vshiftu:
17711 VShiftOpc = ARMISD::VSHLIMM;
17714 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17715 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17716 : ARMISD::VSHRuIMM);
17721 case Intrinsic::arm_neon_vrshifts:
17722 case Intrinsic::arm_neon_vrshiftu:
17727 case Intrinsic::arm_neon_vqshifts:
17728 case Intrinsic::arm_neon_vqshiftu:
17733 case Intrinsic::arm_neon_vqshiftsu:
17738 case Intrinsic::arm_neon_vrshiftn:
17739 case Intrinsic::arm_neon_vqshiftns:
17740 case Intrinsic::arm_neon_vqshiftnu:
17741 case Intrinsic::arm_neon_vqshiftnsu:
17742 case Intrinsic::arm_neon_vqrshiftns:
17743 case Intrinsic::arm_neon_vqrshiftnu:
17744 case Intrinsic::arm_neon_vqrshiftnsu:
17756 case Intrinsic::arm_neon_vshifts:
17757 case Intrinsic::arm_neon_vshiftu:
17760 case Intrinsic::arm_neon_vrshifts:
17761 VShiftOpc = ARMISD::VRSHRsIMM;
17763 case Intrinsic::arm_neon_vrshiftu:
17764 VShiftOpc = ARMISD::VRSHRuIMM;
17766 case Intrinsic::arm_neon_vrshiftn:
17767 VShiftOpc = ARMISD::VRSHRNIMM;
17769 case Intrinsic::arm_neon_vqshifts:
17770 VShiftOpc = ARMISD::VQSHLsIMM;
17772 case Intrinsic::arm_neon_vqshiftu:
17773 VShiftOpc = ARMISD::VQSHLuIMM;
17775 case Intrinsic::arm_neon_vqshiftsu:
17776 VShiftOpc = ARMISD::VQSHLsuIMM;
17778 case Intrinsic::arm_neon_vqshiftns:
17779 VShiftOpc = ARMISD::VQSHRNsIMM;
17781 case Intrinsic::arm_neon_vqshiftnu:
17782 VShiftOpc = ARMISD::VQSHRNuIMM;
17784 case Intrinsic::arm_neon_vqshiftnsu:
17785 VShiftOpc = ARMISD::VQSHRNsuIMM;
17787 case Intrinsic::arm_neon_vqrshiftns:
17788 VShiftOpc = ARMISD::VQRSHRNsIMM;
17790 case Intrinsic::arm_neon_vqrshiftnu:
17791 VShiftOpc = ARMISD::VQRSHRNuIMM;
17793 case Intrinsic::arm_neon_vqrshiftnsu:
17794 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17799 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17800 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17803 case Intrinsic::arm_neon_vshiftins: {
17804 EVT VT =
N->getOperand(1).getValueType();
17806 unsigned VShiftOpc = 0;
17809 VShiftOpc = ARMISD::VSLIIMM;
17810 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17811 VShiftOpc = ARMISD::VSRIIMM;
17817 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17818 N->getOperand(1),
N->getOperand(2),
17822 case Intrinsic::arm_neon_vqrshifts:
17823 case Intrinsic::arm_neon_vqrshiftu:
17827 case Intrinsic::arm_neon_vbsl: {
17829 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17830 N->getOperand(2),
N->getOperand(3));
17832 case Intrinsic::arm_mve_vqdmlah:
17833 case Intrinsic::arm_mve_vqdmlash:
17834 case Intrinsic::arm_mve_vqrdmlah:
17835 case Intrinsic::arm_mve_vqrdmlash:
17836 case Intrinsic::arm_mve_vmla_n_predicated:
17837 case Intrinsic::arm_mve_vmlas_n_predicated:
17838 case Intrinsic::arm_mve_vqdmlah_predicated:
17839 case Intrinsic::arm_mve_vqdmlash_predicated:
17840 case Intrinsic::arm_mve_vqrdmlah_predicated:
17841 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17846 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17853 case Intrinsic::arm_mve_minv:
17854 case Intrinsic::arm_mve_maxv:
17855 case Intrinsic::arm_mve_minav:
17856 case Intrinsic::arm_mve_maxav:
17857 case Intrinsic::arm_mve_minv_predicated:
17858 case Intrinsic::arm_mve_maxv_predicated:
17859 case Intrinsic::arm_mve_minav_predicated:
17860 case Intrinsic::arm_mve_maxav_predicated: {
17863 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17870 case Intrinsic::arm_mve_addv: {
17873 bool Unsigned =
N->getConstantOperandVal(2);
17874 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17878 case Intrinsic::arm_mve_addlv:
17879 case Intrinsic::arm_mve_addlv_predicated: {
17882 bool Unsigned =
N->getConstantOperandVal(2);
17883 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17884 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17885 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17888 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17890 Ops.push_back(
N->getOperand(i));
17903 EVT VT =
Y.getValueType();
17906 if (Subtarget->hasMVEIntegerOps())
17908 if (Subtarget->hasNEON())
17922 EVT VT =
N->getValueType(0);
17924 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17925 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17926 N->getOperand(0)->hasOneUse()) {
17943 if (AndMask == 255 || AndMask == 65535)
17947 if (MaskedBits > ShiftAmt) {
17962 if (ST->hasMVEIntegerOps())
17967 switch (
N->getOpcode()) {
17973 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17980 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17981 unsigned VShiftOpc =
17982 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17984 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
18000 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
18003 EVT FromVT = LD->getValueType(0);
18004 EVT ToVT =
N->getValueType(0);
18011 unsigned NumElements = 0;
18012 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
18014 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
18016 if (NumElements == 0 ||
18026 SDValue BasePtr = LD->getBasePtr();
18027 Align Alignment = LD->getBaseAlign();
18048 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18049 Alignment, MMOFlags, AAInfo);
18055 if (FromEltVT == MVT::f16) {
18058 for (
unsigned i = 0; i < Loads.
size(); i++) {
18060 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
18079 EVT VT =
N->getValueType(0);
18086 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
18093 if (VT == MVT::i32 &&
18094 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
18099 switch (
N->getOpcode()) {
18102 Opc = ARMISD::VGETLANEs;
18106 Opc = ARMISD::VGETLANEu;
18113 if (ST->hasMVEIntegerOps())
18131 Ops.push_back(Ext);
18141 if (ST->hasMVEFloatOps())
18152 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
18156 EVT VT =
Op.getValueType();
18159 if (VT != MVT::i32 ||
18175 APInt MaxC = Max.getConstantOperandAPInt(1);
18176 if (MaxC.
sgt(MinC))
18183 if ((MinC + 1).isPowerOf2()) {
18205 APInt Width = MinC - MaxC + 1;
18208 unsigned SatBit = Width.
logBase2() - 1;
18226 EVT VT =
N->getValueType(0);
18229 if (VT == MVT::i32)
18232 if (!ST->hasMVEIntegerOps())
18238 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18241 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18249 if (VT == MVT::v4i32)
18250 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18252 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18259 MaxC != ~SaturateC)
18264 if (IsSignedSaturate(
N, N0.
getNode())) {
18267 if (VT == MVT::v4i32) {
18268 HalfVT = MVT::v8i16;
18269 ExtVT = MVT::v4i16;
18271 HalfVT = MVT::v16i8;
18286 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18292 if (VT == MVT::v4i32)
18293 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18295 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18304 if (IsUnsignedSaturate(
N)) {
18308 if (VT == MVT::v4i32) {
18309 HalfVT = MVT::v8i16;
18310 ExtConst = 0x0000FFFF;
18312 HalfVT = MVT::v16i8;
18334 const APInt *CV = &
C->getAPIntValue();
18391 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18398 if ((OrCI &
Known.Zero) != OrCI)
18404 EVT VT =
X.getValueType();
18405 unsigned BitInX = AndC->
logBase2();
18413 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18414 BitInY < NumActiveBits; ++BitInY) {
18415 if (OrCI[BitInY] == 0)
18418 Mask.setBit(BitInY);
18419 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18435 switch (
N->getOpcode()) {
18450 if (Const->isZero())
18452 else if (Const->isOne())
18460 unsigned IntOp =
N.getConstantOperandVal(1);
18461 if (IntOp != Intrinsic::test_start_loop_iterations &&
18462 IntOp != Intrinsic::loop_decrement_reg)
18488 bool Negate =
false;
18494 Cond =
N->getOperand(1);
18495 Dest =
N->getOperand(2);
18499 Cond =
N->getOperand(2);
18500 Dest =
N->getOperand(4);
18502 if (!Const->isOne() && !Const->isZero())
18504 Imm = Const->getZExtValue();
18532 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18533 "unsupported condition");
18538 unsigned IntOp =
Int->getConstantOperandVal(1);
18539 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18540 "expected single br user");
18541 SDNode *Br = *
N->user_begin();
18551 if (IntOp == Intrinsic::test_start_loop_iterations) {
18553 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18555 if (IsTrueIfZero(CC, Imm)) {
18557 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18561 UpdateUncondBr(Br, Dest, DAG);
18563 SDValue Ops[] = {Chain, Setup, OtherTarget};
18564 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18576 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18580 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18584 if (
Target == OtherTarget)
18585 UpdateUncondBr(Br, Dest, DAG);
18591 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18600 if (Cmp.getOpcode() != ARMISD::CMPZ)
18605 SDValue LHS = Cmp.getOperand(0);
18606 SDValue RHS = Cmp.getOperand(1);
18615 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18616 LHS->getOperand(0)->hasOneUse() &&
18620 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18632 EVT VT =
N->getValueType(0);
18633 SDValue FalseVal =
N->getOperand(0);
18634 SDValue TrueVal =
N->getOperand(1);
18642 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18649 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18652 if (Cmp.getOpcode() != ARMISD::CMPZ)
18656 SDValue LHS = Cmp.getOperand(0);
18657 SDValue RHS = Cmp.getOperand(1);
18661 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18685 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18686 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18687 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18690 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18695 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18698 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18699 LHS->getOperand(2), LHS->getOperand(3));
18709 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18713 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18715 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18724 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18757 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18769 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18789 const APInt *TrueConst;
18790 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18791 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18792 FalseVal.getOperand(1) == RHS) ||
18796 unsigned ShiftAmount = TrueConst->
logBase2();
18811 if (
Known.Zero == 0xfffffffe)
18814 else if (
Known.Zero == 0xffffff00)
18817 else if (
Known.Zero == 0xffff0000)
18830 EVT DstVT =
N->getValueType(0);
18833 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18834 EVT SrcVT = Src.getValueType();
18836 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18841 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18842 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18843 Src.getValueType().getScalarSizeInBits())
18844 Src = Src.getOperand(0);
18848 EVT SrcVT = Src.getValueType();
18849 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18850 Src.getOpcode() == ARMISD::VMVNIMM ||
18851 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18854 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18868 EVT VT =
N->getValueType(0);
18876 if (
N->getNumOperands() == 2 &&
18880 N->getOperand(0).getOperand(1),
18881 N->getOperand(1).getOperand(0),
18882 N->getOperand(1).getOperand(1));
18885 if (
N->getNumOperands() == 2 &&
18891 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18892 S0->getOperand(1) ==
S1->getOperand(1)) {
18895 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18899 ARMISD::VMOVN,
DL, VT,
18900 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18901 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18905 ARMISD::VMOVN,
DL, VT,
18906 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18907 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18915 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18916 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18917 (Op.getOpcode() == ISD::BITCAST &&
18918 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18921 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18923 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18941 int NumIns =
N->getNumOperands();
18942 assert((NumIns == 2 || NumIns == 4) &&
18943 "Expected 2 or 4 inputs to an MVETrunc");
18945 if (
N->getNumOperands() == 4)
18949 for (
int I = 0;
I < NumIns;
I++) {
18951 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18956 Ptr, MPI, StoreVT,
Align(4));
18971 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18974 EVT FromVT = LD->getMemoryVT();
18975 EVT ToVT =
N->getValueType(0);
18982 unsigned NumElements = 0;
18983 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18985 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18987 assert(NumElements != 0);
18993 LD->getExtensionType() != NewExtType)
19000 SDValue BasePtr = LD->getBasePtr();
19001 Align Alignment = LD->getBaseAlign();
19020 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
19021 Alignment, MMOFlags, AAInfo);
19037 EVT VT =
N->getValueType(0);
19039 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
19040 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
19042 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19044 auto Extend = [&](
SDValue V) {
19053 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
19054 SDValue Ext = Extend(
N->getOperand(0));
19062 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
19063 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
19067 auto CheckInregMask = [&](
int Start,
int Offset) {
19069 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
19075 if (CheckInregMask(0, 0))
19077 else if (CheckInregMask(0, 1))
19078 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19079 else if (CheckInregMask(0, Mask.size()))
19081 else if (CheckInregMask(0, Mask.size() + 1))
19082 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19087 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19091 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19098 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
19109 int NumOuts =
N->getNumValues();
19110 assert((NumOuts == 2 || NumOuts == 4) &&
19111 "Expected 2 or 4 outputs to an MVEEXT");
19112 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19114 if (
N->getNumOperands() == 4)
19120 StackPtr, MPI,
Align(4));
19123 for (
int I = 0;
I < NumOuts;
I++) {
19125 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
19126 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
19131 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
19140 switch (
N->getOpcode()) {
19200 case ARMISD::BRCOND:
19204 case ARMISD::CSINC:
19205 case ARMISD::CSINV:
19206 case ARMISD::CSNEG:
19219 case ARMISD::PREDICATE_CAST:
19221 case ARMISD::VECTOR_REG_CAST:
19232 case ARMISD::VADDVs:
19233 case ARMISD::VADDVu:
19234 case ARMISD::VADDLVs:
19235 case ARMISD::VADDLVu:
19236 case ARMISD::VADDLVAs:
19237 case ARMISD::VADDLVAu:
19238 case ARMISD::VMLAVs:
19239 case ARMISD::VMLAVu:
19240 case ARMISD::VMLALVs:
19241 case ARMISD::VMLALVu:
19242 case ARMISD::VMLALVAs:
19243 case ARMISD::VMLALVAu:
19245 case ARMISD::VMOVN:
19247 case ARMISD::VQMOVNs:
19248 case ARMISD::VQMOVNu:
19250 case ARMISD::VQDMULH:
19256 case ARMISD::SMULWB: {
19257 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19263 case ARMISD::SMULWT: {
19264 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19270 case ARMISD::SMLALBB:
19271 case ARMISD::QADD16b:
19272 case ARMISD::QSUB16b:
19273 case ARMISD::UQADD16b:
19274 case ARMISD::UQSUB16b: {
19275 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19282 case ARMISD::SMLALBT: {
19283 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19285 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19292 case ARMISD::SMLALTB: {
19293 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19295 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19302 case ARMISD::SMLALTT: {
19303 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19310 case ARMISD::QADD8b:
19311 case ARMISD::QSUB8b:
19312 case ARMISD::UQADD8b:
19313 case ARMISD::UQSUB8b: {
19314 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19322 if (
N->getOperand(1) ==
N->getOperand(2))
19323 return N->getOperand(1);
19327 switch (
N->getConstantOperandVal(1)) {
19328 case Intrinsic::arm_neon_vld1:
19329 case Intrinsic::arm_neon_vld1x2:
19330 case Intrinsic::arm_neon_vld1x3:
19331 case Intrinsic::arm_neon_vld1x4:
19332 case Intrinsic::arm_neon_vld2:
19333 case Intrinsic::arm_neon_vld3:
19334 case Intrinsic::arm_neon_vld4:
19335 case Intrinsic::arm_neon_vld2lane:
19336 case Intrinsic::arm_neon_vld3lane:
19337 case Intrinsic::arm_neon_vld4lane:
19338 case Intrinsic::arm_neon_vld2dup:
19339 case Intrinsic::arm_neon_vld3dup:
19340 case Intrinsic::arm_neon_vld4dup:
19341 case Intrinsic::arm_neon_vst1:
19342 case Intrinsic::arm_neon_vst1x2:
19343 case Intrinsic::arm_neon_vst1x3:
19344 case Intrinsic::arm_neon_vst1x4:
19345 case Intrinsic::arm_neon_vst2:
19346 case Intrinsic::arm_neon_vst3:
19347 case Intrinsic::arm_neon_vst4:
19348 case Intrinsic::arm_neon_vst2lane:
19349 case Intrinsic::arm_neon_vst3lane:
19350 case Intrinsic::arm_neon_vst4lane:
19352 case Intrinsic::arm_mve_vld2q:
19353 case Intrinsic::arm_mve_vld4q:
19354 case Intrinsic::arm_mve_vst2q:
19355 case Intrinsic::arm_mve_vst4q:
19372 unsigned *
Fast)
const {
19378 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19381 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19383 if (AllowsUnaligned) {
19385 *
Fast = Subtarget->hasV7Ops();
19390 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19394 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19401 if (!Subtarget->hasMVEIntegerOps())
19405 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19406 Ty == MVT::v2i1)) {
19414 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19430 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19431 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19432 Ty == MVT::v2f64) {
19443 const AttributeList &FuncAttributes)
const {
19445 if ((
Op.isMemcpyOrMemmove() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19446 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19448 if (
Op.size() >= 16 &&
19454 }
else if (
Op.size() >= 8 &&
19471 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19473 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19475 return (SrcBits == 64 && DestBits == 32);
19484 return (SrcBits == 64 && DestBits == 32);
19520 return Subtarget->hasFullFP16();
19527 if (!Subtarget->hasMVEIntegerOps())
19546 if (Ld->isExpandingLoad())
19550 if (Subtarget->hasMVEIntegerOps())
19563 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19595bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19597 if (Subtarget->useSoftFloat())
19606 return Subtarget->hasMVEFloatOps();
19624 unsigned Scale = 1;
19641 if ((V & (Scale - 1)) != 0)
19650 if (VT.
isVector() && Subtarget->hasNEON())
19653 !Subtarget->hasMVEFloatOps())
19656 bool IsNeg =
false;
19662 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19665 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19681 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19687 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19717 default:
return false;
19736 int Scale = AM.
Scale;
19741 default:
return false;
19749 Scale = Scale & ~1;
19750 return Scale == 2 || Scale == 4 || Scale == 8;
19767 if (Scale & 1)
return false;
19774 const int Scale = AM.
Scale;
19784 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19800 switch (AM.
Scale) {
19811 if (Subtarget->isThumb1Only())
19814 if (Subtarget->isThumb2())
19817 int Scale = AM.
Scale;
19819 default:
return false;
19823 if (Scale < 0) Scale = -Scale;
19831 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19844 if (Scale & 1)
return false;
19857 if (!Subtarget->isThumb())
19860 if (Subtarget->isThumb2())
19864 return Imm >= 0 && Imm <= 255;
19874 if (!Subtarget->isThumb())
19876 if (Subtarget->isThumb2())
19879 return AbsImm <= 255;
19914 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19918 int RHSC = (int)
RHS->getZExtValue();
19919 if (RHSC < 0 && RHSC > -256) {
19929 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19932 int RHSC = (int)
RHS->getZExtValue();
19933 if (RHSC < 0 && RHSC > -0x1000) {
19975 int RHSC = (int)
RHS->getZExtValue();
19976 if (RHSC < 0 && RHSC > -0x100) {
19981 }
else if (RHSC > 0 && RHSC < 0x100) {
19992 bool isSEXTLoad,
bool IsMasked,
bool isLE,
20003 bool CanChangeType = isLE && !IsMasked;
20006 int RHSC = (int)
RHS->getZExtValue();
20008 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
20009 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
20014 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
20025 if (VT == MVT::v4i16) {
20026 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
20028 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
20029 if (IsInRange(RHSC, 0x80, 1))
20031 }
else if (Alignment >= 4 &&
20032 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
20033 IsInRange(RHSC, 0x80, 4))
20035 else if (Alignment >= 2 &&
20036 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
20037 IsInRange(RHSC, 0x80, 2))
20039 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
20052 if (Subtarget->isThumb1Only())
20059 bool isSEXTLoad =
false;
20060 bool IsMasked =
false;
20062 Ptr = LD->getBasePtr();
20063 VT = LD->getMemoryVT();
20064 Alignment = LD->getAlign();
20065 AS = LD->getAddressSpace();
20068 Ptr = ST->getBasePtr();
20069 VT = ST->getMemoryVT();
20070 Alignment = ST->getAlign();
20071 AS = ST->getAddressSpace();
20073 Ptr = LD->getBasePtr();
20074 VT = LD->getMemoryVT();
20075 Alignment = LD->getAlign();
20076 AS = LD->getAddressSpace();
20080 Ptr = ST->getBasePtr();
20081 VT = ST->getMemoryVT();
20082 Alignment = ST->getAlign();
20083 AS = ST->getAddressSpace();
20098 bool isLegal =
false;
20100 isLegal = Subtarget->hasMVEIntegerOps() &&
20102 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
20103 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
20105 if (Subtarget->isThumb2())
20130 bool isSEXTLoad =
false, isNonExt;
20131 bool IsMasked =
false;
20133 VT = LD->getMemoryVT();
20134 Ptr = LD->getBasePtr();
20135 Alignment = LD->getAlign();
20139 VT = ST->getMemoryVT();
20140 Ptr = ST->getBasePtr();
20141 Alignment = ST->getAlign();
20142 isNonExt = !ST->isTruncatingStore();
20144 VT = LD->getMemoryVT();
20145 Ptr = LD->getBasePtr();
20146 Alignment = LD->getAlign();
20151 VT = ST->getMemoryVT();
20152 Ptr = ST->getBasePtr();
20153 Alignment = ST->getAlign();
20154 isNonExt = !ST->isTruncatingStore();
20159 if (Subtarget->isThumb1Only()) {
20162 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
20163 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
20166 if (!RHS || RHS->getZExtValue() != 4)
20168 if (Alignment <
Align(4))
20172 Base =
Op->getOperand(0);
20178 bool isLegal =
false;
20180 isLegal = Subtarget->hasMVEIntegerOps() &&
20185 if (Subtarget->isThumb2())
20199 !Subtarget->isThumb2())
20213 const APInt &DemandedElts,
20215 unsigned Depth)
const {
20218 switch (
Op.getOpcode()) {
20225 if (
Op.getResNo() == 0) {
20236 case ARMISD::CMOV: {
20239 if (
Known.isUnknown())
20251 case Intrinsic::arm_ldaex:
20252 case Intrinsic::arm_ldrex: {
20260 case ARMISD::BFI: {
20267 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20268 Known.Zero &= Mask;
20272 case ARMISD::VGETLANEs:
20273 case ARMISD::VGETLANEu: {
20274 const SDValue &SrcSV =
Op.getOperand(0);
20280 "VGETLANE index out of bounds");
20285 EVT VT =
Op.getValueType();
20291 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20299 case ARMISD::VMOVrh: {
20305 case ARMISD::CSINC:
20306 case ARMISD::CSINV:
20307 case ARMISD::CSNEG: {
20315 if (
Op.getOpcode() == ARMISD::CSINC)
20318 else if (
Op.getOpcode() == ARMISD::CSINV)
20320 else if (
Op.getOpcode() == ARMISD::CSNEG)
20327 case ARMISD::VORRIMM:
20328 case ARMISD::VBICIMM: {
20329 unsigned Encoded =
Op.getConstantOperandVal(1);
20330 unsigned DecEltBits = 0;
20333 unsigned EltBits =
Op.getScalarValueSizeInBits();
20334 if (EltBits != DecEltBits) {
20343 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20344 APInt Imm(DecEltBits, DecodedVal);
20346 Known.One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20347 Known.Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20355 if (!Subtarget->isThumb())
20372 if (Imm == 0 || Imm == ~0U)
20375 unsigned Opc =
Op.getOpcode();
20377 EVT VT =
Op.getValueType();
20379 unsigned ShrunkImm = Imm & Demanded;
20380 unsigned ExpandedImm = Imm | ~Demanded;
20382 auto IsLegalImm = [ShrunkImm, ExpandedImm](
unsigned CandidateImm) ->
bool {
20383 return (ShrunkImm & CandidateImm) == ShrunkImm &&
20384 (~ExpandedImm & CandidateImm) == 0;
20386 auto UseImm = [Imm,
Opc,
Op, VT, &TLO](
unsigned NewImm) ->
bool {
20398 if (ShrunkImm == 0) {
20399 ++NumOptimizedImms;
20400 return UseImm(ShrunkImm);
20406 if (ExpandedImm == ~0U) {
20407 ++NumOptimizedImms;
20408 return UseImm(ExpandedImm);
20416 if (IsLegalImm(0xFF)) {
20417 ++NumOptimizedImms;
20418 return UseImm(0xFF);
20421 if (IsLegalImm(0xFFFF)) {
20422 ++NumOptimizedImms;
20423 return UseImm(0xFFFF);
20437 ++NumOptimizedImms;
20438 return UseImm(ShrunkImm);
20446 if ((~ExpandedImm) < 256) {
20447 ++NumOptimizedImms;
20448 return UseImm(ExpandedImm);
20454 !Subtarget->hasV6Ops()) {
20455 ++NumOptimizedImms;
20456 return UseImm(ExpandedImm);
20475 EVT VT =
Op.getValueType();
20490 switch (
Op.getOpcode()) {
20501 unsigned Imm =
C->getZExtValue();
20508 unsigned Depth)
const {
20509 unsigned Opc =
Op.getOpcode();
20513 case ARMISD::LSRL: {
20517 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20519 unsigned ShAmt =
Op->getConstantOperandVal(2);
20529 case ARMISD::VBICIMM: {
20531 unsigned ModImm =
Op.getConstantOperandVal(1);
20532 unsigned EltBits = 0;
20534 if ((OriginalDemandedBits & Mask) == 0)
20540 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
20555 if (!Subtarget->hasVFP2Base())
20559 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20571 unsigned S = Constraint.
size();
20573 switch (Constraint[0]) {
20585 }
else if (S == 2) {
20586 switch (Constraint[0]) {
20603 Value *CallOperandVal =
info.CallOperandVal;
20606 if (!CallOperandVal)
20610 switch (*constraint) {
20616 if (Subtarget->isThumb())
20631 if (PR == 0 || VT == MVT::Other)
20633 if (ARM::SPRRegClass.
contains(PR))
20634 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20635 if (ARM::DPRRegClass.
contains(PR))
20640using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20644 switch (Constraint.
size()) {
20647 switch (Constraint[0]) {
20649 if (Subtarget->isThumb())
20650 return RCPair(0U, &ARM::tGPRRegClass);
20651 return RCPair(0U, &ARM::GPRRegClass);
20653 if (Subtarget->isThumb())
20654 return RCPair(0U, &ARM::hGPRRegClass);
20657 if (Subtarget->isThumb1Only())
20658 return RCPair(0U, &ARM::tGPRRegClass);
20659 return RCPair(0U, &ARM::GPRRegClass);
20661 if (VT == MVT::Other)
20663 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20664 return RCPair(0U, &ARM::SPRRegClass);
20666 return RCPair(0U, &ARM::DPRRegClass);
20668 return RCPair(0U, &ARM::QPRRegClass);
20671 if (VT == MVT::Other)
20673 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20674 return RCPair(0U, &ARM::SPR_8RegClass);
20676 return RCPair(0U, &ARM::DPR_8RegClass);
20678 return RCPair(0U, &ARM::QPR_8RegClass);
20681 if (VT == MVT::Other)
20683 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20684 return RCPair(0U, &ARM::SPRRegClass);
20686 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20688 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20694 if (Constraint[0] ==
'T') {
20695 switch (Constraint[1]) {
20699 return RCPair(0U, &ARM::tGPREvenRegClass);
20701 return RCPair(0U, &ARM::tGPROddRegClass);
20710 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20711 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20714 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20715 return std::make_pair(
unsigned(ARM::LR),
getRegClassFor(MVT::i32));
20719 return {0,
nullptr};
20727 std::vector<SDValue> &
Ops,
20732 if (Constraint.
size() != 1)
20735 char ConstraintLetter = Constraint[0];
20736 switch (ConstraintLetter) {
20739 case 'I':
case 'J':
case 'K':
case 'L':
20740 case 'M':
case 'N':
case 'O':
20745 int64_t CVal64 =
C->getSExtValue();
20746 int CVal = (int) CVal64;
20749 if (CVal != CVal64)
20752 switch (ConstraintLetter) {
20756 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20757 if (CVal >= 0 && CVal <= 65535)
20761 if (Subtarget->isThumb1Only()) {
20764 if (CVal >= 0 && CVal <= 255)
20766 }
else if (Subtarget->isThumb2()) {
20780 if (Subtarget->isThumb1Only()) {
20785 if (CVal >= -255 && CVal <= -1)
20791 if (CVal >= -4095 && CVal <= 4095)
20797 if (Subtarget->isThumb1Only()) {
20804 }
else if (Subtarget->isThumb2()) {
20824 if (Subtarget->isThumb1Only()) {
20827 if (CVal >= -7 && CVal < 7)
20829 }
else if (Subtarget->isThumb2()) {
20849 if (Subtarget->isThumb1Only()) {
20852 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20858 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20864 if (Subtarget->isThumb1Only()) {
20866 if (CVal >= 0 && CVal <= 31)
20872 if (Subtarget->isThumb1Only()) {
20875 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20884 if (Result.getNode()) {
20885 Ops.push_back(Result);
20895 "Unhandled Opcode in getDivRemLibcall");
20901 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20902 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20903 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20904 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20913 "Unhandled Opcode in getDivRemArgList");
20917 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20918 EVT ArgVT =
N->getOperand(i).getValueType();
20923 Args.push_back(Entry);
20931 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20932 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20933 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20934 "Register-based DivRem lowering only");
20935 unsigned Opcode =
Op->getOpcode();
20937 "Invalid opcode for Div/Rem lowering");
20939 EVT VT =
Op->getValueType(0);
20961 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20962 : Subtarget->hasDivideInARMMode();
20963 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20964 Op->getSimpleValueType(0) == MVT::i32) {
20966 const SDValue Dividend =
Op->getOperand(0);
20967 const SDValue Divisor =
Op->getOperand(1);
20968 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20991 if (
getTM().getTargetTriple().isOSWindows())
20994 TargetLowering::CallLoweringInfo CLI(DAG);
20998 Callee, std::move(Args))
21003 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
21004 return CallInfo.first;
21010 EVT VT =
N->getValueType(0);
21016 Result[0], Result[1]);
21020 std::vector<Type*> RetTyParams;
21021 Type *RetTyElement;
21031 RetTyParams.push_back(RetTyElement);
21032 RetTyParams.push_back(RetTyElement);
21047 if (
getTM().getTargetTriple().isOSWindows())
21054 Callee, std::move(Args))
21058 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
21061 SDNode *ResNode = CallResult.first.getNode();
21068 assert(
getTM().getTargetTriple().isOSWindows() &&
21069 "unsupported target platform");
21077 "no-stack-arg-probe")) {
21081 Chain =
SP.getValue(1);
21098 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
21099 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
21109 bool IsStrict =
Op->isStrictFPOpcode();
21110 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21111 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21113 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
21114 "Unexpected type for custom-lowering FP_EXTEND");
21116 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21117 "With both FP DP and 16, any FP conversion is legal!");
21119 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
21120 "With FP16, 16 to 32 conversion is legal!");
21123 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
21128 Loc,
Op.getValueType(), SrcVal);
21143 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
21144 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
21145 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
21146 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
21150 {DstVT, MVT::Other}, {Chain, SrcVal});
21157 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21158 "Unexpected type for custom-lowering FP_EXTEND");
21159 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21164 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
21168 bool IsStrict =
Op->isStrictFPOpcode();
21170 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21172 EVT DstVT =
Op.getValueType();
21174 if (DstVT == MVT::bf16) {
21175 if (Subtarget->hasBF16() && SrcVT == MVT::f32)
21180 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21183 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
21184 "Unexpected type for custom-lowering FP_ROUND");
21186 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21187 "With both FP DP and 16, any FP conversion is legal!");
21192 if (SrcSz == 32 && Subtarget->hasFP16())
21197 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21198 "Unexpected type for custom-lowering FP_ROUND");
21202 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21214 if (v == 0xffffffff)
21226 bool ForCodeSize)
const {
21227 if (!Subtarget->hasVFP3Base())
21229 if (VT == MVT::f16 && Subtarget->hasFullFP16())
21231 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
21234 if (VT == MVT::f32)
21236 if (VT == MVT::f64 && Subtarget->hasFP64())
21249 case Intrinsic::arm_neon_vld1:
21250 case Intrinsic::arm_neon_vld2:
21251 case Intrinsic::arm_neon_vld3:
21252 case Intrinsic::arm_neon_vld4:
21253 case Intrinsic::arm_neon_vld2lane:
21254 case Intrinsic::arm_neon_vld3lane:
21255 case Intrinsic::arm_neon_vld4lane:
21256 case Intrinsic::arm_neon_vld2dup:
21257 case Intrinsic::arm_neon_vld3dup:
21258 case Intrinsic::arm_neon_vld4dup: {
21261 auto &
DL =
I.getDataLayout();
21262 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21264 Info.ptrVal =
I.getArgOperand(0);
21266 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21273 case Intrinsic::arm_neon_vld1x2:
21274 case Intrinsic::arm_neon_vld1x3:
21275 case Intrinsic::arm_neon_vld1x4: {
21278 auto &
DL =
I.getDataLayout();
21279 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21281 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
21283 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
21289 case Intrinsic::arm_neon_vst1:
21290 case Intrinsic::arm_neon_vst2:
21291 case Intrinsic::arm_neon_vst3:
21292 case Intrinsic::arm_neon_vst4:
21293 case Intrinsic::arm_neon_vst2lane:
21294 case Intrinsic::arm_neon_vst3lane:
21295 case Intrinsic::arm_neon_vst4lane: {
21298 auto &
DL =
I.getDataLayout();
21299 unsigned NumElts = 0;
21300 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21301 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21304 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21307 Info.ptrVal =
I.getArgOperand(0);
21309 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21316 case Intrinsic::arm_neon_vst1x2:
21317 case Intrinsic::arm_neon_vst1x3:
21318 case Intrinsic::arm_neon_vst1x4: {
21321 auto &
DL =
I.getDataLayout();
21322 unsigned NumElts = 0;
21323 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21324 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21327 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21330 Info.ptrVal =
I.getArgOperand(0);
21332 Info.align =
I.getParamAlign(0).valueOrOne();
21338 case Intrinsic::arm_mve_vld2q:
21339 case Intrinsic::arm_mve_vld4q: {
21343 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21345 Info.ptrVal =
I.getArgOperand(0);
21353 case Intrinsic::arm_mve_vst2q:
21354 case Intrinsic::arm_mve_vst4q: {
21357 Type *VecTy =
I.getArgOperand(1)->getType();
21358 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21360 Info.ptrVal =
I.getArgOperand(0);
21368 case Intrinsic::arm_mve_vldr_gather_base:
21369 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21371 Info.ptrVal =
nullptr;
21373 Info.align =
Align(1);
21378 case Intrinsic::arm_mve_vldr_gather_base_wb:
21379 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21381 Info.ptrVal =
nullptr;
21382 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21383 Info.align =
Align(1);
21388 case Intrinsic::arm_mve_vldr_gather_offset:
21389 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21391 Info.ptrVal =
nullptr;
21396 Info.align =
Align(1);
21401 case Intrinsic::arm_mve_vstr_scatter_base:
21402 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21404 Info.ptrVal =
nullptr;
21405 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21406 Info.align =
Align(1);
21411 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21412 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21414 Info.ptrVal =
nullptr;
21415 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21416 Info.align =
Align(1);
21421 case Intrinsic::arm_mve_vstr_scatter_offset:
21422 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21424 Info.ptrVal =
nullptr;
21429 Info.align =
Align(1);
21434 case Intrinsic::arm_ldaex:
21435 case Intrinsic::arm_ldrex: {
21436 auto &
DL =
I.getDataLayout();
21437 Type *ValTy =
I.getParamElementType(0);
21440 Info.ptrVal =
I.getArgOperand(0);
21442 Info.align =
DL.getABITypeAlign(ValTy);
21447 case Intrinsic::arm_stlex:
21448 case Intrinsic::arm_strex: {
21449 auto &
DL =
I.getDataLayout();
21450 Type *ValTy =
I.getParamElementType(1);
21453 Info.ptrVal =
I.getArgOperand(1);
21455 Info.align =
DL.getABITypeAlign(ValTy);
21460 case Intrinsic::arm_stlexd:
21461 case Intrinsic::arm_strexd:
21463 Info.memVT = MVT::i64;
21464 Info.ptrVal =
I.getArgOperand(2);
21466 Info.align =
Align(8);
21471 case Intrinsic::arm_ldaexd:
21472 case Intrinsic::arm_ldrexd:
21474 Info.memVT = MVT::i64;
21475 Info.ptrVal =
I.getArgOperand(0);
21477 Info.align =
Align(8);
21491 assert(Ty->isIntegerTy());
21493 unsigned Bits = Ty->getPrimitiveSizeInBits();
21494 if (Bits == 0 || Bits > 32)
21500 unsigned Index)
const {
21510 if (!Subtarget->hasDataBarrier()) {
21514 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21515 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21516 Builder.getInt32(0), Builder.getInt32(7),
21517 Builder.getInt32(10), Builder.getInt32(5)};
21518 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_mcr,
args);
21527 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_dmb, CDomain);
21548 if (Subtarget->preferISHSTBarriers())
21581 bool has64BitAtomicStore;
21582 if (Subtarget->isMClass())
21583 has64BitAtomicStore =
false;
21584 else if (Subtarget->isThumb())
21585 has64BitAtomicStore = Subtarget->hasV7Ops();
21587 has64BitAtomicStore = Subtarget->hasV6Ops();
21589 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21603 bool has64BitAtomicLoad;
21604 if (Subtarget->isMClass())
21605 has64BitAtomicLoad =
false;
21606 else if (Subtarget->isThumb())
21607 has64BitAtomicLoad = Subtarget->hasV7Ops();
21609 has64BitAtomicLoad = Subtarget->hasV6Ops();
21625 if (Subtarget->isMClass())
21626 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21627 else if (Subtarget->isThumb())
21628 hasAtomicRMW = Subtarget->hasV7Ops();
21630 hasAtomicRMW = Subtarget->hasV6Ops();
21631 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21655 bool HasAtomicCmpXchg;
21656 if (Subtarget->isMClass())
21657 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21658 else if (Subtarget->isThumb())
21659 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21661 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21663 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21670 return InsertFencesForAtomic;
21675 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21681 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21682 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21684 RTLIB::LibcallImpl SecurityCookieVar =
21685 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21686 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21687 SecurityCookieVar != RTLIB::Unsupported) {
21698 F->addParamAttr(0, Attribute::AttrKind::InReg);
21705 unsigned &
Cost)
const {
21707 if (!Subtarget->hasNEON())
21736 unsigned Opcode =
Op.getOpcode();
21738 case ARMISD::VORRIMM:
21739 case ARMISD::VBICIMM:
21743 Op, DemandedElts, DAG, Kind, ConsiderFlags,
Depth);
21747 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21751 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21756 if (!Subtarget->hasV7Ops())
21762 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21764 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21772 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21781 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21787 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21789 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21792 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21794 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21795 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21796 if (!Subtarget->isLittle())
21798 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21799 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21800 return Builder.CreateOr(
21801 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21805 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21806 CallInst *CI = Builder.CreateIntrinsicWithoutFolding(
Int, Tys, Addr);
21809 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21810 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21815 if (!Subtarget->hasV7Ops())
21817 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21823 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21831 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21834 Value *
Lo = Builder.CreateTrunc(Val, Int32Ty,
"lo");
21835 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32), Int32Ty,
"hi");
21836 if (!Subtarget->isLittle())
21838 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21841 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21845 CallInst *CI = Builder.CreateCall(
21846 Strex, {Builder.CreateZExtOrBitCast(
21856 return Subtarget->isMClass();
21864 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21871 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21874 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21882 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21890 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21893 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21898 if (Subtarget->hasNEON() && VecSize == 64)
21900 return VecSize % 128 == 0;
21904 if (Subtarget->hasNEON())
21906 if (Subtarget->hasMVEIntegerOps())
21926 "Invalid interleave factor");
21927 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21929 "Unmatched number of shufflevectors and indices");
21934 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21937 Type *EltTy = VecTy->getElementType();
21940 Align Alignment = LI->getAlign();
21958 Value *BaseAddr = LI->getPointerOperand();
21960 if (NumLoads > 1) {
21964 VecTy->getNumElements() / NumLoads);
21970 if (Subtarget->hasNEON()) {
21971 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21972 Type *Tys[] = {VecTy, PtrTy};
21973 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21974 Intrinsic::arm_neon_vld3,
21975 Intrinsic::arm_neon_vld4};
21978 Ops.push_back(BaseAddr);
21979 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21981 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21984 assert((Factor == 2 || Factor == 4) &&
21985 "expected interleave factor of 2 or 4 for MVE");
21987 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21988 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21989 Type *Tys[] = {VecTy, PtrTy};
21992 Ops.push_back(BaseAddr);
21993 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
22003 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
22007 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
22008 VecTy->getNumElements() * Factor);
22014 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
22016 unsigned Index = Indices[i];
22018 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
22022 SubVec = Builder.CreateIntToPtr(
22026 SubVecs[SV].push_back(SubVec);
22035 auto &SubVec = SubVecs[SVI];
22038 SVI->replaceAllUsesWith(WideVec);
22074 const APInt &GapMask)
const {
22076 "Invalid interleave factor");
22081 "Unexpected mask on store");
22084 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
22086 unsigned LaneLen = VecTy->getNumElements() / Factor;
22087 Type *EltTy = VecTy->getElementType();
22091 Align Alignment =
SI->getAlign();
22108 Type *IntTy =
DL.getIntPtrType(EltTy);
22113 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
22114 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
22120 Value *BaseAddr =
SI->getPointerOperand();
22122 if (NumStores > 1) {
22125 LaneLen /= NumStores;
22135 if (Subtarget->hasNEON()) {
22136 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
22137 Intrinsic::arm_neon_vst3,
22138 Intrinsic::arm_neon_vst4};
22139 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22140 Type *Tys[] = {PtrTy, SubVecTy};
22143 Ops.push_back(BaseAddr);
22145 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
22146 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
22148 assert((Factor == 2 || Factor == 4) &&
22149 "expected interleave factor of 2 or 4 for MVE");
22151 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
22152 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22153 Type *Tys[] = {PtrTy, SubVecTy};
22156 Ops.push_back(BaseAddr);
22158 for (
unsigned F = 0;
F < Factor;
F++) {
22159 Ops.push_back(Builder.getInt32(
F));
22160 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
22166 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
22169 if (StoreCount > 0)
22170 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
22171 BaseAddr, LaneLen * Factor);
22176 for (
unsigned i = 0; i < Factor; i++) {
22177 unsigned IdxI = StoreCount * LaneLen * Factor + i;
22178 if (Mask[IdxI] >= 0) {
22179 Shuffles.
push_back(Builder.CreateShuffleVector(
22182 unsigned StartMask = 0;
22183 for (
unsigned j = 1; j < LaneLen; j++) {
22184 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
22185 if (Mask[IdxJ * Factor + IdxI] >= 0) {
22186 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
22196 Shuffles.
push_back(Builder.CreateShuffleVector(
22217 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
22221 Members += SubMembers;
22227 Members += SubMembers * AT->getNumElements();
22228 }
else if (Ty->isFloatTy()) {
22233 }
else if (Ty->isDoubleTy()) {
22245 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
22247 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
22249 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
22262 return (Members > 0 && Members <= 4);
22268 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
22270 return ABITypeAlign;
22275 assert(StackAlign &&
"data layout string is missing stack alignment");
22276 return std::min(ABITypeAlign, *StackAlign);
22285 if (getEffectiveCallingConv(CallConv, isVarArg) !=
22294 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
22295 return IsHA || IsIntArray;
22299 const Constant *PersonalityFn)
const {
22307 const Constant *PersonalityFn)
const {
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,...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void 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 isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for this result type with this index.
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...
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...
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.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
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.
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & 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...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
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 getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
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 ...
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.
ExceptionHandling getExceptionModel() const
Return the ExceptionHandling to use, considering TargetOptions and the Triple's default.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
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).
@ SjLj
setjmp/longjmp based exceptions
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
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...
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
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)