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()) {
886 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
889 if (Subtarget->hasFullFP16()) {
897 if (!Subtarget->hasFP16()) {
926 if (!Subtarget->isThumb1Only()) {
945 if (TT.isTargetAEABI() && !Subtarget->allowsUnalignedMem()) {
957 if (!Subtarget->isThumb1Only()) {
966 if (Subtarget->hasDSP()) {
976 if (Subtarget->hasBaseDSP()) {
984 if (Subtarget->isThumb1Only()) {
988 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
989 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1004 if (Subtarget->hasMVEIntegerOps())
1008 if (Subtarget->isThumb1Only()) {
1014 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1028 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1037 if (Subtarget->hasPerfMon())
1041 if (!Subtarget->hasV6Ops())
1044 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1045 : Subtarget->hasDivideInARMMode();
1052 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1064 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1065 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1068 HasStandaloneRem =
false;
1095 if (TT.isOSWindows())
1102 InsertFencesForAtomic =
false;
1103 if (Subtarget->hasAnyDataBarrier() &&
1104 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1108 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1113 if (!Subtarget->hasAcquireRelease() ||
1116 InsertFencesForAtomic =
true;
1122 if (Subtarget->hasDataBarrier())
1123 InsertFencesForAtomic =
true;
1143 if (!InsertFencesForAtomic) {
1150 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1162 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1163 Subtarget->hasForced32BitAtomics()) {
1177 if (!Subtarget->hasV6Ops()) {
1183 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1184 !Subtarget->isThumb1Only()) {
1213 if (Subtarget->hasFullFP16()) {
1223 if (Subtarget->hasFullFP16())
1238 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1239 !Subtarget->isThumb1Only()) {
1246 if (!Subtarget->hasVFP4Base()) {
1252 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1254 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1262 if (!Subtarget->hasFP16()) {
1279 if (Subtarget->hasFPARMv8Base()) {
1289 if (Subtarget->hasFP64())
1293 if (Subtarget->hasNEON()) {
1303 if (Subtarget->hasFullFP16()) {
1340 if (Subtarget->hasNEON()) {
1352 if (Subtarget->hasV8Ops()) {
1362 if (Subtarget->hasFullFP16()) {
1385 if (TT.isOSWindows()) {
1402 if (Subtarget->hasMVEIntegerOps())
1405 if (Subtarget->hasV6Ops())
1407 if (Subtarget->isThumb1Only())
1410 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1411 Subtarget->isThumb2()) {
1417 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1418 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1440 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1448 return Subtarget->useSoftFloat();
1452 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1465std::pair<const TargetRegisterClass *, uint8_t>
1476 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1477 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1478 RRC = &ARM::DPRRegClass;
1483 if (Subtarget->useNEONForSinglePrecisionFP())
1486 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1487 case MVT::v4f32:
case MVT::v2f64:
1488 RRC = &ARM::DPRRegClass;
1492 RRC = &ARM::DPRRegClass;
1496 RRC = &ARM::DPRRegClass;
1500 return std::make_pair(RRC,
Cost);
1509 if (Subtarget->hasMVEIntegerOps())
1524 if (Subtarget->hasNEON()) {
1525 if (VT == MVT::v4i64)
1526 return &ARM::QQPRRegClass;
1527 if (VT == MVT::v8i64)
1528 return &ARM::QQQQPRRegClass;
1530 if (Subtarget->hasMVEIntegerOps()) {
1531 if (VT == MVT::v4i64)
1532 return &ARM::MQQPRRegClass;
1533 if (VT == MVT::v8i64)
1534 return &ARM::MQQQQPRRegClass;
1543 Align &PrefAlign)
const {
1550 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1562 unsigned NumVals =
N->getNumValues();
1566 for (
unsigned i = 0; i != NumVals; ++i) {
1567 EVT VT =
N->getValueType(i);
1568 if (VT == MVT::Glue || VT == MVT::Other)
1574 if (!
N->isMachineOpcode())
1582 if (
MCID.getNumDefs() == 0)
1584 if (!Itins->isEmpty() &&
1585 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1599 return Const->getZExtValue() == 16;
1607 return Const->getZExtValue() == 16;
1615 return Const->getZExtValue() == 16;
1684 bool isVarArg)
const {
1703 if (!
getTM().isAAPCS_ABI())
1705 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1713 if (!
getTM().isAAPCS_ABI()) {
1714 if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() && !isVarArg)
1717 }
else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1726 bool isVarArg)
const {
1727 return CCAssignFnForNode(CC,
false, isVarArg);
1731 bool isVarArg)
const {
1732 return CCAssignFnForNode(CC,
true, isVarArg);
1739 bool isVarArg)
const {
1740 switch (getEffectiveCallingConv(CC, isVarArg)) {
1766 if (Subtarget->hasFullFP16()) {
1767 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1779 if (Subtarget->hasFullFP16()) {
1780 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1793SDValue ARMTargetLowering::LowerCallResult(
1797 SDValue ThisVal,
bool isCmseNSCall)
const {
1805 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1806 CCValAssign VA = RVLocs[i];
1810 if (i == 0 && isThisReturn) {
1812 "unexpected return calling convention register assignment");
1830 if (!Subtarget->isLittle())
1832 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1847 if (!Subtarget->isLittle())
1849 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1879 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1890std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1892 bool IsTailCall,
int SPDiff)
const {
1894 MachinePointerInfo DstInfo;
1914 return std::make_pair(DstAddr, DstInfo);
1923ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1936 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1939 int SrcFI = SrcFrameIdxNode->getIndex();
1940 int DstFI = DstFrameIdxNode->getIndex();
1942 "byval passed in non-fixed stack slot");
1964 if (SrcOffset == DstOffset)
1972 RegsToPassVector &RegsToPass,
1979 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1980 unsigned id = Subtarget->isLittle() ? 0 : 1;
1992 MachinePointerInfo DstInfo;
1993 std::tie(DstAddr, DstInfo) =
1994 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2011 SelectionDAG &DAG = CLI.
DAG;
2013 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2014 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2015 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2022 const CallBase *CB = CLI.
CB;
2025 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2027 MachineFunction::CallSiteInfo CSInfo;
2028 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2029 bool isThisReturn =
false;
2030 bool isCmseNSCall =
false;
2031 bool isSibCall =
false;
2032 bool PreferIndirect =
false;
2033 bool GuardWithBTI =
false;
2043 !Subtarget->noBTIAtReturnTwice())
2051 isCmseNSCall =
true;
2054 if (!Subtarget->supportsTailCall())
2070 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2071 count_if(GV->users(), [&BB](
const User *U) {
2072 return isa<Instruction>(U) &&
2073 cast<Instruction>(U)->getParent() == BB;
2080 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2094 "site marked musttail");
2097 unsigned NumBytes = CCInfo.getStackSize();
2106 if (isTailCall && !isSibCall) {
2107 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2108 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2113 assert(StackAlign &&
"data layout string is missing stack alignment");
2114 NumBytes =
alignTo(NumBytes, *StackAlign);
2119 SPDiff = NumReusableBytes - NumBytes;
2123 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2139 RegsToPassVector RegsToPass;
2148 DenseMap<unsigned, SDValue> ByValTemporaries;
2152 for (
const CCValAssign &VA : ArgLocs) {
2154 SDValue Src = OutVals[ArgIdx];
2155 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2157 if (!
Flags.isByVal())
2161 MachinePointerInfo DstInfo;
2162 std::tie(Dst, DstInfo) =
2163 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2164 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2166 if (Copy == NoCopy) {
2171 }
else if (Copy == CopyOnce) {
2175 ByValTemporaries[ArgIdx] = Src;
2177 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2181 int TempFrameIdx = MFI.CreateStackObject(
2182 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2190 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2191 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2193 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2194 ByValTemporaries[ArgIdx] = Temp;
2197 if (!ByValCopyChains.
empty())
2207 bool AfterFormalArgLoads =
false;
2211 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2213 ++i, ++realArgIdx) {
2214 CCValAssign &VA = ArgLocs[i];
2215 SDValue Arg = OutVals[realArgIdx];
2216 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2217 bool isByVal =
Flags.isByVal();
2237 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2239 if (ByValTempChain) {
2244 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2245 if (Outs[
I].
Flags.isByVal())
2253 FrameIndexSDNode *FIN =
2258 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2261 for (
const CCValAssign &VA : ArgLocs) {
2269 if (!IncomingLoad.
empty()) {
2277 AfterFormalArgLoads =
true;
2289 auto ArgVT = Outs[realArgIdx].ArgVT;
2290 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2308 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2309 StackPtr, MemOpChains, isTailCall, SPDiff);
2313 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2314 StackPtr, MemOpChains, isTailCall, SPDiff);
2318 MachinePointerInfo DstInfo;
2319 std::tie(DstAddr, DstInfo) =
2320 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2324 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2325 StackPtr, MemOpChains, isTailCall, SPDiff);
2327 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2328 Outs[0].VT == MVT::i32) {
2330 "unexpected calling convention register assignment");
2332 "unexpected use of 'returned'");
2333 isThisReturn =
true;
2338 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2339 }
else if (isByVal) {
2341 unsigned offset = 0;
2345 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2346 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2349 bool NeedsStackCopy;
2350 if (
auto It = ByValTemporaries.
find(realArgIdx);
2351 It != ByValTemporaries.
end()) {
2352 ByValSrc = It->second;
2353 NeedsStackCopy =
true;
2356 NeedsStackCopy = !isTailCall;
2360 if (CurByValIdx < ByValArgsCount) {
2361 unsigned RegBegin, RegEnd;
2362 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2366 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2370 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2373 RegsToPass.push_back(std::make_pair(j, Load));
2378 offset = RegEnd - RegBegin;
2380 CCInfo.nextInRegsParam();
2385 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2388 MachinePointerInfo DstInfo;
2389 std::tie(Dst, DstInfo) =
2390 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2398 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2399 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2406 MachinePointerInfo DstInfo;
2407 std::tie(DstAddr, DstInfo) =
2408 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2415 if (!MemOpChains.
empty())
2421 for (
const auto &[
Reg,
N] : RegsToPass) {
2429 bool isDirect =
false;
2432 const Triple &
TT = TM.getTargetTriple();
2433 const GlobalValue *GVal =
nullptr;
2435 GVal =
G->getGlobal();
2436 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2438 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2439 bool isLocalARMFunc =
false;
2442 if (Subtarget->genLongCalls()) {
2444 "long-calls codegen is not position independent!");
2449 if (Subtarget->genExecuteOnly()) {
2450 if (Subtarget->useMovt())
2462 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2468 const char *Sym = S->getSymbol();
2470 if (Subtarget->genExecuteOnly()) {
2471 if (Subtarget->useMovt())
2483 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2490 if (!PreferIndirect) {
2495 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2497 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2498 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2500 ARMISD::WrapperPIC, dl, PtrVt,
2507 }
else if (Subtarget->isTargetCOFF()) {
2508 assert(Subtarget->isTargetWindows() &&
2509 "Windows is the only supported COFF target");
2513 else if (!TM.shouldAssumeDSOLocal(GVal))
2520 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2529 const char *Sym = S->getSymbol();
2530 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2532 ARMConstantPoolValue *CPV =
2534 ARMPCLabelIndex, 4);
2536 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2541 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2548 assert(!isARMFunc && !isDirect &&
2549 "Cannot handle call to ARM function or direct call");
2553 "call to non-secure function would require "
2554 "passing arguments on stack",
2560 "call to non-secure function would return value through pointer",
2567 if (Subtarget->isThumb()) {
2569 CallOpc = ARMISD::t2CALL_BTI;
2570 else if (isCmseNSCall)
2571 CallOpc = ARMISD::tSECALL;
2572 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2573 CallOpc = ARMISD::CALL_NOLINK;
2575 CallOpc = ARMISD::CALL;
2577 if (!isDirect && !Subtarget->hasV5TOps())
2578 CallOpc = ARMISD::CALL_NOLINK;
2579 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2581 !Subtarget->hasMinSize())
2583 CallOpc = ARMISD::CALL_NOLINK;
2585 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2592 if (isTailCall && !isSibCall) {
2597 std::vector<SDValue>
Ops;
2598 Ops.push_back(Chain);
2599 Ops.push_back(Callee);
2607 for (
const auto &[
Reg,
N] : RegsToPass)
2611 const uint32_t *
Mask;
2612 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2620 isThisReturn =
false;
2626 assert(Mask &&
"Missing call preserved mask for calling convention");
2630 Ops.push_back(InGlue);
2643 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2654 uint64_t CalleePopBytes =
2657 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2663 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2664 InVals, isThisReturn,
2665 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2672void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2673 Align Alignment)
const {
2675 Alignment = std::max(Alignment,
Align(4));
2681 unsigned AlignInRegs = Alignment.
value() / 4;
2682 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2683 for (
unsigned i = 0; i < Waste; ++i)
2689 unsigned Excess = 4 * (ARM::R4 -
Reg);
2696 if (NSAAOffset != 0 &&
Size > Excess) {
2708 unsigned ByValRegBegin =
Reg;
2709 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2713 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2719 Size = std::max<int>(
Size - Excess, 0);
2727bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2733 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2734 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2735 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2736 const SelectionDAG &DAG = CLI.
DAG;
2741 assert(Subtarget->supportsTailCall());
2754 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2756 if (!(Subtarget->isThumb1Only() ||
2757 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2758 AddressRegisters.
insert(ARM::R12);
2759 for (
const CCValAssign &AL : ArgLocs)
2761 AddressRegisters.
erase(
AL.getLocReg());
2762 if (AddressRegisters.
empty()) {
2763 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2782 <<
" (guaranteed tail-call CC)\n");
2783 return CalleeCC == CallerCC;
2788 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2790 if (isCalleeStructRet != isCallerStructRet) {
2803 const GlobalValue *GV =
G->getGlobal();
2806 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2807 TT.isOSBinFormatMachO())) {
2816 getEffectiveCallingConv(CalleeCC, isVarArg),
2817 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
2824 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2825 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2826 if (CalleeCC != CallerCC) {
2827 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2828 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2837 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2845 const MachineRegisterInfo &MRI = MF.
getRegInfo();
2847 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2866 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2875 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2888 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2891 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2895 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2900 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2922 bool isLittleEndian = Subtarget->isLittle();
2925 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2934 "secure entry function would return value through pointer",
2939 for (
unsigned i = 0, realRVLocIdx = 0;
2941 ++i, ++realRVLocIdx) {
2942 CCValAssign &VA = RVLocs[i];
2945 SDValue Arg = OutVals[realRVLocIdx];
2946 bool ReturnF16 =
false;
2948 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
2981 auto RetVT = Outs[realRVLocIdx].ArgVT;
3003 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3007 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3013 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3025 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3027 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3032 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3042 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3068 !Subtarget->isMClass()) {
3069 if (Subtarget->isThumb1Only())
3076 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3079bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3080 if (
N->getNumValues() != 1)
3082 if (!
N->hasNUsesOfValue(1, 0))
3086 SDNode *
Copy = *
N->user_begin();
3090 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3092 TCChain =
Copy->getOperand(0);
3093 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3094 SDNode *VMov =
Copy;
3096 SmallPtrSet<SDNode*, 2>
Copies;
3097 for (SDNode *U : VMov->
users()) {
3105 for (SDNode *U : VMov->
users()) {
3106 SDValue UseChain =
U->getOperand(0);
3114 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3122 if (!
Copy->hasOneUse())
3129 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3131 TCChain =
Copy->getOperand(0);
3136 bool HasRet =
false;
3137 for (
const SDNode *U :
Copy->users()) {
3138 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3139 U->getOpcode() != ARMISD::INTRET_GLUE)
3151bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3152 if (!Subtarget->supportsTailCall())
3169 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3185 EVT PtrVT =
Op.getValueType();
3195 if (Subtarget->genExecuteOnly()) {
3200 auto GV =
new GlobalVariable(
3206 return LowerGlobalAddress(GA, DAG);
3212 if (Subtarget->isThumb1Only())
3213 CPAlign = std::max(CPAlign,
Align(4));
3219 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3226 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3235 unsigned ARMPCLabelIndex = 0;
3241 if (!IsPositionIndependent) {
3244 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3251 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3255 if (!IsPositionIndependent)
3258 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3286ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3289 "This function expects a Darwin target");
3294 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3300 MVT::i32,
DL, Chain, DescAddr,
3315 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3324 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3330ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3333 "Windows specific TLS lowering");
3357 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3365 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3366 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3372 MachinePointerInfo());
3379 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3392 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3394 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3396 ARMConstantPoolValue *CPV =
3407 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3414 TargetLowering::CallLoweringInfo CLI(DAG);
3419 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3420 return CallResult.first;
3429 const GlobalValue *GV = GA->
getGlobal();
3435 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3439 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3442 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3443 ARMConstantPoolValue *CPV =
3450 PtrVT, dl, Chain,
Offset,
3458 PtrVT, dl, Chain,
Offset,
3463 ARMConstantPoolValue *CPV =
3468 PtrVT, dl, Chain,
Offset,
3484 if (
TT.isOSDarwin())
3485 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3487 if (
TT.isOSWindows())
3488 return LowerGlobalTLSAddressWindows(
Op, DAG);
3491 assert(
TT.isOSBinFormatELF() &&
"Only ELF implemented here");
3497 return LowerToTLSGeneralDynamicModel(GA, DAG);
3500 return LowerToTLSExecModels(GA, DAG, model);
3509 while (!Worklist.
empty()) {
3517 if (!
I ||
I->getParent()->getParent() !=
F)
3546 if (!GVar || !GVar->hasInitializer() ||
3547 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3548 !GVar->hasLocalLinkage())
3553 auto *
Init = GVar->getInitializer();
3555 Init->needsDynamicRelocation())
3567 unsigned RequiredPadding = 4 - (
Size % 4);
3568 bool PaddingPossible =
3569 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3574 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3598 if (RequiredPadding != 4) {
3603 while (RequiredPadding--)
3615 ++NumConstpoolPromoted;
3616 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3621 if (!(GV = GA->getAliaseeObject()))
3624 return V->isConstant();
3633 return LowerGlobalAddressWindows(
Op, DAG);
3635 return LowerGlobalAddressELF(
Op, DAG);
3637 return LowerGlobalAddressDarwin(
Op, DAG);
3649 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3667 }
else if (Subtarget->isROPI() && IsRO) {
3672 }
else if (Subtarget->isRWPI() && !IsRO) {
3675 if (Subtarget->useMovt()) {
3678 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3680 ARMConstantPoolValue *CPV =
3683 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3697 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3698 if (Subtarget->useMovt())
3702 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3706 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3715 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3716 "ROPI/RWPI not currently supported for Darwin");
3721 if (Subtarget->useMovt())
3732 if (Subtarget->isGVIndirectSymbol(GV))
3741 "non-Windows COFF is not supported");
3742 assert(Subtarget->useMovt() &&
3743 "Windows on ARM expects to use movw/movt");
3744 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3745 "ROPI/RWPI not currently supported for Windows");
3752 else if (!TM.shouldAssumeDSOLocal(GV))
3775 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3776 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3777 Op.getOperand(1), Val);
3783 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3790 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3794SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3797 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3801 case Intrinsic::arm_gnu_eabi_mcount: {
3807 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3808 const uint32_t *
Mask =
3810 assert(Mask &&
"Missing call preserved mask for calling convention");
3815 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3819 if (Subtarget->isThumb())
3822 ARM::tBL_PUSHLR, dl, ResultTys,
3823 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3824 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3828 {ReturnAddress, Callee, RegisterMask, Chain}),
3837 unsigned IntNo =
Op.getConstantOperandVal(0);
3841 case Intrinsic::localaddress: {
3843 const auto *RegInfo = Subtarget->getRegisterInfo();
3844 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
3846 Op.getSimpleValueType());
3848 case Intrinsic::eh_recoverfp: {
3854 "llvm.eh.recoverfp must take a function as the first argument");
3855 const auto *RegInfo = Subtarget->getRegisterInfo();
3858 MachineBasicBlock &
MBB = *MF.
begin();
3864 case Intrinsic::thread_pointer: {
3866 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3868 case Intrinsic::arm_cls: {
3872 const SDValue &Operand =
Op.getOperand(1);
3873 const EVT VTy =
Op.getValueType();
3876 case Intrinsic::arm_cls64: {
3882 case Intrinsic::arm_neon_vcls:
3883 case Intrinsic::arm_mve_vcls: {
3886 const EVT VTy =
Op.getValueType();
3889 case Intrinsic::eh_sjlj_lsda: {
3891 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3896 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3897 ARMConstantPoolValue *CPV =
3901 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3906 if (IsPositionIndependent) {
3908 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3912 case Intrinsic::arm_neon_vabs:
3915 case Intrinsic::arm_neon_vabds:
3916 if (
Op.getValueType().isInteger())
3918 Op.getOperand(1),
Op.getOperand(2));
3920 case Intrinsic::arm_neon_vabdu:
3922 Op.getOperand(1),
Op.getOperand(2));
3923 case Intrinsic::arm_neon_vmulls:
3924 case Intrinsic::arm_neon_vmullu: {
3925 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3926 ? ARMISD::VMULLs : ARMISD::VMULLu;
3927 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3928 Op.getOperand(1),
Op.getOperand(2));
3930 case Intrinsic::arm_neon_vminnm:
3931 case Intrinsic::arm_neon_vmaxnm: {
3932 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3934 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3935 Op.getOperand(1),
Op.getOperand(2));
3937 case Intrinsic::arm_neon_vminu:
3938 case Intrinsic::arm_neon_vmaxu: {
3939 if (
Op.getValueType().isFloatingPoint())
3941 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3943 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3944 Op.getOperand(1),
Op.getOperand(2));
3946 case Intrinsic::arm_neon_vmins:
3947 case Intrinsic::arm_neon_vmaxs: {
3949 if (!
Op.getValueType().isFloatingPoint()) {
3950 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3952 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3953 Op.getOperand(1),
Op.getOperand(2));
3955 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3957 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3958 Op.getOperand(1),
Op.getOperand(2));
3960 case Intrinsic::arm_neon_vtbl1:
3961 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
3962 Op.getOperand(1),
Op.getOperand(2));
3963 case Intrinsic::arm_neon_vtbl2:
3964 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
3965 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3966 case Intrinsic::arm_mve_pred_i2v:
3967 case Intrinsic::arm_mve_pred_v2i:
3968 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
3970 case Intrinsic::arm_mve_vreinterpretq:
3971 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
3973 case Intrinsic::arm_mve_lsll:
3974 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
3975 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3976 case Intrinsic::arm_mve_asrl:
3977 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
3978 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3979 case Intrinsic::arm_mve_vsli:
3980 return DAG.
getNode(ARMISD::VSLIIMM, SDLoc(
Op),
Op->getVTList(),
3981 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3982 case Intrinsic::arm_mve_vsri:
3983 return DAG.
getNode(ARMISD::VSRIIMM, SDLoc(
Op),
Op->getVTList(),
3984 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3995 if (!Subtarget->hasDataBarrier()) {
3999 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4000 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4001 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
4011 }
else if (Subtarget->preferISHSTBarriers() &&
4020 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4028 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4030 return Op.getOperand(0);
4033 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4035 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4037 return Op.getOperand(0);
4039 unsigned isData =
Op.getConstantOperandVal(4);
4040 if (Subtarget->isThumb()) {
4042 isRead = ~isRead & 1;
4043 isData = ~isData & 1;
4046 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4061 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4069 const SDLoc &dl)
const {
4071 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4073 const TargetRegisterClass *RC;
4075 RC = &ARM::tGPRRegClass;
4077 RC = &ARM::GPRRegClass;
4091 MVT::i32, dl, Root, FIN,
4097 if (!Subtarget->isLittle())
4099 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4112 const Value *OrigArg,
4113 unsigned InRegsParamRecordIdx,
4114 int ArgOffset,
unsigned ArgSize)
const {
4128 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4129 unsigned RBegin, REnd;
4134 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4139 ArgOffset = -4 * (ARM::R4 - RBegin);
4146 const TargetRegisterClass *RC =
4149 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4153 MachinePointerInfo(OrigArg, 4 * i));
4158 if (!MemOps.
empty())
4167 unsigned TotalArgRegsSaveSize,
4168 bool ForceMutable)
const {
4170 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4179 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4183bool ARMTargetLowering::splitValueIntoRegisterParts(
4185 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4187 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4199SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4201 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4202 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4215SDValue ARMTargetLowering::LowerFormalArguments(
4222 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4231 unsigned CurArgIdx = 0;
4243 unsigned ArgRegBegin = ARM::R4;
4244 for (
const CCValAssign &VA : ArgLocs) {
4250 if (!
Flags.isByVal())
4254 unsigned RBegin, REnd;
4256 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4262 int lastInsIndex = -1;
4266 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4269 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4273 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4274 CCValAssign &VA = ArgLocs[i];
4275 if (Ins[VA.
getValNo()].isOrigArg()) {
4276 std::advance(CurOrigArg,
4277 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4278 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4289 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4296 MVT::f64, dl, Chain, FIN,
4299 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4307 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4309 const TargetRegisterClass *RC;
4311 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4312 RC = &ARM::HPRRegClass;
4313 else if (RegVT == MVT::f32)
4314 RC = &ARM::SPRRegClass;
4315 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4316 RegVT == MVT::v4bf16)
4317 RC = &ARM::DPRRegClass;
4318 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4319 RegVT == MVT::v8bf16)
4320 RC = &ARM::QPRRegClass;
4321 else if (RegVT == MVT::i32)
4323 : &ARM::GPRRegClass;
4360 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4369 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4375 if (index != lastInsIndex)
4377 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4383 if (
Flags.isByVal()) {
4384 assert(Ins[index].isOrigArg() &&
4385 "Byval arguments cannot be implicit");
4389 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4423 lastInsIndex = index;
4430 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4431 TotalArgRegsSaveSize);
4435 "secure entry function must not be variadic", dl.
getDebugLoc()));
4445 assert(StackAlign &&
"data layout string is missing stack alignment");
4446 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4455 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4464 return CFP->getValueAPF().isPosZero();
4467 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4468 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4471 return CFP->getValueAPF().isPosZero();
4474 Op->getValueType(0) == MVT::f64) {
4478 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4487 if (
Op->getFlags().hasNoSignedWrap())
4503 (isIntEqualitySetCC(CC) ||
4512 const SDLoc &dl)
const {
4514 unsigned C = RHSC->getZExtValue();
4578 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4582 unsigned Mask =
LHS.getConstantOperandVal(1);
4584 uint64_t RHSV = RHSC->getZExtValue();
4585 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4587 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4601 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4604 LHS.getConstantOperandVal(1) < 31) {
4605 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4630 unsigned CompareType;
4633 CompareType = ARMISD::CMP;
4638 CompareType = ARMISD::CMPZ;
4647 if (CompareType != ARMISD::CMPZ &&
isCMN(
RHS, CC, DAG)) {
4648 CompareType = ARMISD::CMN;
4650 }
else if (CompareType != ARMISD::CMPZ &&
isCMN(
LHS, CC, DAG)) {
4651 CompareType = ARMISD::CMN;
4663 bool Signaling)
const {
4664 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4670 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4679std::pair<SDValue, SDValue>
4682 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4694 switch (
Op.getOpcode()) {
4746 return std::make_pair(
Value, OverflowCmp);
4759 return Cmp.getValue(1);
4787 return DAG.
getNode(ARMISD::CMOV,
DL, VT, Zero, One, ARMcc, Flags);
4799 EVT VT =
Op.getValueType();
4800 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4803 switch (
Op.getOpcode()) {
4817 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4823 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4826 ARMcc, OverflowCmp);
4836 EVT VT =
Op.getValueType();
4837 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4847 switch (
Op->getOpcode()) {
4849 NewOpcode = ARMISD::UQADD8b;
4852 NewOpcode = ARMISD::QADD8b;
4855 NewOpcode = ARMISD::UQSUB8b;
4858 NewOpcode = ARMISD::QSUB8b;
4863 switch (
Op->getOpcode()) {
4865 NewOpcode = ARMISD::UQADD16b;
4868 NewOpcode = ARMISD::QADD16b;
4871 NewOpcode = ARMISD::UQSUB16b;
4874 NewOpcode = ARMISD::QSUB16b;
4882 DAG.
getNode(NewOpcode, dl, MVT::i32,
4893 unsigned Opc =
Cond.getOpcode();
4895 if (
Cond.getResNo() == 1 &&
4903 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4904 EVT VT =
Op.getValueType();
4906 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4914 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4915 const ConstantSDNode *CMOVTrue =
4917 const ConstantSDNode *CMOVFalse =
4920 if (CMOVTrue && CMOVFalse) {
4926 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
4928 False = SelectFalse;
4929 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
4935 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
4936 Cond.getOperand(3), DAG);
4946 bool &swpCmpOps,
bool &swpVselOps) {
4974 swpCmpOps = !swpCmpOps;
4975 swpVselOps = !swpVselOps;
4998 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5000 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5002 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5016 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5037 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5039 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5060 EVT VT =
Op.getValueType();
5082 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5095 int64_t PosVal = std::max(Val1, Val2);
5096 int64_t NegVal = std::min(Val1, Val2);
5108 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5111 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5143 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5148 if (*K != KTmp || V != VTmp)
5159bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5161 return !Subtarget->hasVFP2Base();
5163 return !Subtarget->hasFP64();
5165 return !Subtarget->hasFullFP16();
5173 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5181 if (TVal == ~FVal) {
5182 Opcode = ARMISD::CSINV;
5183 }
else if (TVal == ~FVal + 1) {
5184 Opcode = ARMISD::CSNEG;
5185 }
else if (TVal + 1 == FVal) {
5186 Opcode = ARMISD::CSINC;
5187 }
else if (TVal == FVal + 1) {
5188 Opcode = ARMISD::CSINC;
5191 InvertCond = !InvertCond;
5198 if (Opcode != ARMISD::CSINC &&
5202 InvertCond = !InvertCond;
5208 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5211 InvertCond = !InvertCond;
5218 EVT VT =
Op.getValueType();
5222 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5234 if (VT == MVT::i32 &&
5253 if (
Op.getValueType().isInteger()) {
5261 LHS.getValueType() ==
RHS.getValueType()) {
5262 EVT VT =
LHS.getValueType();
5268 Shift = DAG.
getNOT(dl, Shift, VT);
5280 if (
LHS.getValueType() == MVT::i32) {
5284 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5290 EVT VT =
Op.getValueType();
5291 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5295 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5300 if (!
RHS.getNode()) {
5306 if (
LHS.getValueType() == MVT::i32) {
5317 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5318 TrueVal.getValueType() == MVT::f32 ||
5319 TrueVal.getValueType() == MVT::f64)) {
5333 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5343 if (Subtarget->hasFPARMv8Base() &&
5345 (
TrueVal.getValueType() == MVT::f16 ||
5346 TrueVal.getValueType() == MVT::f32 ||
5347 TrueVal.getValueType() == MVT::f64)) {
5348 bool swpCmpOps =
false;
5349 bool swpVselOps =
false;
5363 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5366 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5376 if (!
N->hasOneUse())
5379 if (!
N->getNumValues())
5381 EVT VT =
Op.getValueType();
5382 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5399 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5400 Ld->getPointerInfo(), Ld->getAlign(),
5401 Ld->getMemOperand()->getFlags());
5417 SDValue Ptr = Ld->getBasePtr();
5419 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5420 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5425 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5426 Ld->getPointerInfo().getWithOffset(4),
5428 Ld->getMemOperand()->getFlags());
5446 bool LHSSeenZero =
false;
5448 bool RHSSeenZero =
false;
5450 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5461 if (
LHS.getValueType() == MVT::f32) {
5467 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5479 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5480 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5495 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5514 unsigned Opc =
Cond.getOpcode();
5516 !Subtarget->isThumb1Only();
5517 if (
Cond.getResNo() == 1 &&
5527 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5532 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5547 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5552 if (!
RHS.getNode()) {
5560 unsigned Opc =
LHS.getOpcode();
5562 !Subtarget->isThumb1Only();
5574 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5581 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5585 if (
LHS.getValueType() == MVT::i32) {
5588 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5591 SDNodeFlags
Flags =
Op->getFlags();
5592 if (
Flags.hasNoNaNs() &&
5597 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5611 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5625 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5628 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5633 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5634 Addr,
Op.getOperand(2), JTI);
5638 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5642 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5645 DAG.
getLoad(PTy, dl, Chain, Addr,
5648 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5653 EVT VT =
Op.getValueType();
5656 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5657 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5665 const EVT OpTy =
Op.getOperand(0).getValueType();
5666 if (OpTy == MVT::v4f32)
5668 else if (OpTy == MVT::v4f16 && HasFullFP16)
5670 else if (OpTy == MVT::v8f16 && HasFullFP16)
5675 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5678 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5683 EVT VT =
Op.getValueType();
5687 bool IsStrict =
Op->isStrictFPOpcode();
5688 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5690 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5703 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5704 CallOptions, Loc, Chain);
5714 Loc,
Op.getValueType(), SrcVal);
5723 EVT VT =
Op.getValueType();
5725 EVT FromVT =
Op.getOperand(0).getValueType();
5727 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5729 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5730 Subtarget->hasFP64())
5732 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5733 Subtarget->hasFullFP16())
5735 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5736 Subtarget->hasMVEFloatOps())
5738 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5739 Subtarget->hasMVEFloatOps())
5742 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5759 EVT VT =
Op.getValueType();
5762 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5768 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5769 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5770 "Invalid type for custom lowering!");
5775 if (VT == MVT::v4f32)
5776 DestVecType = MVT::v4i32;
5777 else if (VT == MVT::v4f16 && HasFullFP16)
5778 DestVecType = MVT::v4i16;
5779 else if (VT == MVT::v8f16 && HasFullFP16)
5780 DestVecType = MVT::v8i16;
5786 switch (
Op.getOpcode()) {
5798 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5803 EVT VT =
Op.getValueType();
5806 if (isUnsupportedFloatingType(VT)) {
5816 CallOptions, SDLoc(
Op)).first;
5827 EVT VT =
Op.getValueType();
5831 bool UseNEON = !InGPR && Subtarget->hasNEON();
5838 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5845 if (SrcVT == MVT::f32) {
5848 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5851 }
else if (VT == MVT::f32)
5852 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5867 if (VT == MVT::f32) {
5879 if (SrcVT == MVT::f64)
5888 if (VT == MVT::f32) {
5901 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5909 EVT VT =
Op.getValueType();
5911 unsigned Depth =
Op.getConstantOperandVal(0);
5913 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5917 MachinePointerInfo());
5926 const ARMBaseRegisterInfo &ARI =
5927 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
5932 EVT VT =
Op.getValueType();
5934 unsigned Depth =
Op.getConstantOperandVal(0);
5939 MachinePointerInfo());
5947 return StringSwitch<Register>(
RegName)
5948 .Case(
"sp", ARM::SP)
5959 assert(
N->getValueType(0) == MVT::i64
5960 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
5963 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6003 const APInt &APIntIndex = Index->getAPIntValue();
6005 NewIndex *= APIntIndex;
6034 EVT SrcVT =
Op.getValueType();
6035 EVT DstVT =
N->getValueType(0);
6037 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6038 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6039 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6042 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6043 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6044 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6051 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6063 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6071 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6073 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6075 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6095 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6104 EVT VT =
Op.getValueType();
6126 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6136 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6147 EVT VT =
Op.getValueType();
6168 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6189 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6241 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6269 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6299 EVT VT =
N->getValueType(0);
6300 if (VT.
isVector() && ST->hasNEON()) {
6309 if (ElemTy == MVT::i8) {
6317 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6320 unsigned NumBits = ElemTy.getSizeInBits();
6322 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6332 if (ElemTy == MVT::i64) {
6345 if (!ST->hasV6T2Ops())
6354 EVT VT =
N->getValueType(0);
6357 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6358 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6359 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6360 "Unexpected type for custom ctpop lowering");
6368 unsigned EltSize = 8;
6391 Op =
Op.getOperand(0);
6393 APInt SplatBits, SplatUndef;
6394 unsigned SplatBitSize;
6397 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6399 SplatBitSize > ElementBits)
6410 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6414 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6425 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6430 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6431 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6440 EVT VT =
N->getValueType(0);
6455 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6457 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6462 "unexpected vector shift opcode");
6464 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6465 unsigned VShiftOpc =
6466 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6467 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6473 EVT ShiftVT =
N->getOperand(1).getValueType();
6476 unsigned VShiftOpc =
6477 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6478 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6483 EVT VT =
N->getValueType(0);
6492 "Unknown shift to lower!");
6494 unsigned ShOpc =
N->getOpcode();
6495 if (ST->hasMVEIntegerOps()) {
6497 unsigned ShPartsOpc = ARMISD::LSLL;
6518 ShPartsOpc = ARMISD::LSRL;
6520 ShPartsOpc = ARMISD::ASRL;
6525 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6539 if (ST->isThumb1Only())
6544 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6548 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6552 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6560 bool Invert =
false;
6567 EVT VT =
Op.getValueType();
6575 assert(ST->hasMVEIntegerOps() &&
6576 "No hardware support for integer vector comparison!");
6578 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6599 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6603 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6613 switch (SetCCOpcode) {
6617 if (ST->hasMVEFloatOps()) {
6620 Invert =
true; [[fallthrough]];
6625 case ISD::SETLT: Swap =
true; [[fallthrough]];
6629 case ISD::SETLE: Swap =
true; [[fallthrough]];
6645 Result = DAG.
getNOT(dl, Result, VT);
6648 case ISD::SETUO: Invert =
true; [[fallthrough]];
6657 Result = DAG.
getNOT(dl, Result, VT);
6663 switch (SetCCOpcode) {
6666 if (ST->hasMVEIntegerOps()) {
6669 Invert =
true; [[fallthrough]];
6672 case ISD::SETLT: Swap =
true; [[fallthrough]];
6674 case ISD::SETLE: Swap =
true; [[fallthrough]];
6691 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6694 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6699 Result = DAG.
getNOT(dl, Result, VT);
6724 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6727 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6733 Result = DAG.
getNOT(dl, Result, VT);
6742 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6759 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6770 unsigned OpCmode, Imm;
6781 switch (SplatBitSize) {
6786 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6789 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6794 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6795 if ((SplatBits & ~0xff) == 0) {
6801 if ((SplatBits & ~0xff00) == 0) {
6804 Imm = SplatBits >> 8;
6814 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6815 if ((SplatBits & ~0xff) == 0) {
6821 if ((SplatBits & ~0xff00) == 0) {
6824 Imm = SplatBits >> 8;
6827 if ((SplatBits & ~0xff0000) == 0) {
6830 Imm = SplatBits >> 16;
6833 if ((SplatBits & ~0xff000000) == 0) {
6836 Imm = SplatBits >> 24;
6843 if ((SplatBits & ~0xffff) == 0 &&
6844 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6847 Imm = SplatBits >> 8;
6855 if ((SplatBits & ~0xffffff) == 0 &&
6856 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6859 Imm = SplatBits >> 16;
6875 unsigned ImmMask = 1;
6877 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6878 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6880 }
else if ((SplatBits & BitMask) != 0) {
6889 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6903 EVT VT =
Op.getValueType();
6904 bool IsDouble = (VT == MVT::f64);
6910 if (
ST->genExecuteOnly()) {
6912 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6913 "Unexpected architecture");
6931 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
6936 if (!
ST->hasVFP3Base())
6941 if (IsDouble && !Subtarget->hasFP64())
6948 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
6966 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
6975 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7029 unsigned ExpectedElt = Imm;
7030 for (
unsigned i = 1; i < NumElts; ++i) {
7034 if (ExpectedElt == NumElts)
7037 if (M[i] < 0)
continue;
7038 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7046 bool &ReverseVEXT,
unsigned &Imm) {
7048 ReverseVEXT =
false;
7059 unsigned ExpectedElt = Imm;
7060 for (
unsigned i = 1; i < NumElts; ++i) {
7064 if (ExpectedElt == NumElts * 2) {
7069 if (M[i] < 0)
continue;
7070 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7085 return VT == MVT::v8i8 && M.size() == 8;
7090 if (Mask.size() == Elements * 2)
7091 return Index / Elements;
7092 return Mask[Index] == 0 ? 0 : 1;
7122 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7130 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7132 for (
unsigned j = 0; j < NumElts; j += 2) {
7133 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7134 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7139 if (M.size() == NumElts*2)
7154 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7157 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7159 for (
unsigned j = 0; j < NumElts; j += 2) {
7160 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7161 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7166 if (M.size() == NumElts*2)
7186 if (M.size() != NumElts && M.size() != NumElts*2)
7189 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7191 for (
unsigned j = 0; j < NumElts; ++j) {
7192 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7197 if (M.size() == NumElts*2)
7216 if (M.size() != NumElts && M.size() != NumElts*2)
7219 unsigned Half = NumElts / 2;
7220 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7222 for (
unsigned j = 0; j < NumElts; j += Half) {
7223 unsigned Idx = WhichResult;
7224 for (
unsigned k = 0; k < Half; ++k) {
7225 int MIdx = M[i + j + k];
7226 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7233 if (M.size() == NumElts*2)
7257 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7260 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7262 unsigned Idx = WhichResult * NumElts / 2;
7263 for (
unsigned j = 0; j < NumElts; j += 2) {
7264 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7265 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7271 if (M.size() == NumElts*2)
7290 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7293 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7295 unsigned Idx = WhichResult * NumElts / 2;
7296 for (
unsigned j = 0; j < NumElts; j += 2) {
7297 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7298 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7304 if (M.size() == NumElts*2)
7317 unsigned &WhichResult,
7320 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7321 return ARMISD::VTRN;
7322 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7323 return ARMISD::VUZP;
7324 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7325 return ARMISD::VZIP;
7329 return ARMISD::VTRN;
7331 return ARMISD::VUZP;
7333 return ARMISD::VZIP;
7342 if (NumElts != M.size())
7346 for (
unsigned i = 0; i != NumElts; ++i)
7347 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7356 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7364 int Ofs = Top ? 1 : 0;
7365 int Upper = SingleSource ? 0 : NumElts;
7366 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7367 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7369 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7378 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7387 unsigned Offset = Top ? 0 : 1;
7388 unsigned N = SingleSource ? 0 : NumElts;
7389 for (
unsigned i = 0; i < NumElts; i += 2) {
7390 if (M[i] >= 0 && M[i] != (
int)i)
7392 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7401 if (NumElts != M.size())
7409 unsigned Off0 = rev ? NumElts / 2 : 0;
7410 unsigned Off1 = rev ? 0 : NumElts / 2;
7411 for (
unsigned i = 0; i < NumElts; i += 2) {
7412 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7414 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7430 if (!ST->hasMVEFloatOps())
7435 if (VT != MVT::v8f16)
7456 for (
unsigned i = 1; i < 4; i++) {
7471 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7483 if (!ST->hasMVEFloatOps())
7488 if (VT != MVT::v4f32)
7504 for (
unsigned i = 1; i < 4; i++) {
7515 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7527 Val =
N->getAsZExtVal();
7529 if (ST->isThumb1Only()) {
7530 if (Val <= 255 || ~Val <= 255)
7542 EVT VT =
Op.getValueType();
7544 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7548 unsigned BitsPerBool;
7552 }
else if (NumElts == 4) {
7555 }
else if (NumElts == 8) {
7558 }
else if (NumElts == 16) {
7569 return U.get().isUndef() || U.get() == FirstOp;
7573 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7577 unsigned Bits32 = 0;
7578 for (
unsigned i = 0; i < NumElts; ++i) {
7582 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7584 Bits32 |= BoolMask << (i * BitsPerBool);
7590 for (
unsigned i = 0; i < NumElts; ++i) {
7603 if (!ST->hasMVEIntegerOps())
7607 EVT VT =
Op.getValueType();
7617 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7621 for (
unsigned I = 2;
I < NumElts;
I++) {
7637 switch (
N->getOpcode()) {
7648 return N->getOperand(1).getNode() ==
Op;
7650 switch (
N->getConstantOperandVal(0)) {
7651 case Intrinsic::arm_mve_add_predicated:
7652 case Intrinsic::arm_mve_mul_predicated:
7653 case Intrinsic::arm_mve_qadd_predicated:
7654 case Intrinsic::arm_mve_vhadd:
7655 case Intrinsic::arm_mve_hadd_predicated:
7656 case Intrinsic::arm_mve_vqdmulh:
7657 case Intrinsic::arm_mve_qdmulh_predicated:
7658 case Intrinsic::arm_mve_vqrdmulh:
7659 case Intrinsic::arm_mve_qrdmulh_predicated:
7660 case Intrinsic::arm_mve_vqdmull:
7661 case Intrinsic::arm_mve_vqdmull_predicated:
7663 case Intrinsic::arm_mve_sub_predicated:
7664 case Intrinsic::arm_mve_qsub_predicated:
7665 case Intrinsic::arm_mve_vhsub:
7666 case Intrinsic::arm_mve_hsub_predicated:
7667 return N->getOperand(2).getNode() ==
Op;
7682 EVT VT =
Op.getValueType();
7690 APInt SplatBits, SplatUndef;
7691 unsigned SplatBitSize;
7693 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7700 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7702 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7703 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7704 : SplatBitSize == 16 ? MVT::v8i16
7708 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7711 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7712 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7717 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7721 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7725 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7727 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7731 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7735 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7739 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7745 if (
ST->hasMVEIntegerOps() &&
7746 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7747 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7748 : SplatBitSize == 16 ? MVT::v8i16
7752 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7765 bool isOnlyLowElement =
true;
7766 bool usesOnlyOneValue =
true;
7767 bool hasDominantValue =
false;
7772 DenseMap<SDValue, unsigned> ValueCounts;
7774 for (
unsigned i = 0; i < NumElts; ++i) {
7779 isOnlyLowElement =
false;
7783 unsigned &
Count = ValueCounts[
V];
7786 if (++
Count > (NumElts / 2)) {
7787 hasDominantValue =
true;
7791 if (ValueCounts.
size() != 1)
7792 usesOnlyOneValue =
false;
7793 if (!
Value.getNode() && !ValueCounts.
empty())
7796 if (ValueCounts.
empty())
7802 (VT != MVT::v8f16 ||
ST->hasFullFP16()))
7809 if (hasDominantValue && EltSize <= 32) {
7818 ConstantSDNode *constIndex;
7825 if (VT !=
Value->getOperand(0).getValueType()) {
7828 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7833 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7838 if (!usesOnlyOneValue) {
7841 for (
unsigned I = 0;
I < NumElts; ++
I) {
7846 Ops.push_back(
Op.getOperand(
I));
7856 assert(FVT == MVT::f32 || FVT == MVT::f16);
7857 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7858 for (
unsigned i = 0; i < NumElts; ++i)
7863 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7867 if (usesOnlyOneValue) {
7870 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7894 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7914 if (EltSize >= 32) {
7920 for (
unsigned i = 0; i < NumElts; ++i)
7933 (VT == MVT::v8f16 && !
ST->hasFullFP16())) {
7935 for (
unsigned i = 0 ; i < NumElts; ++i) {
7954 EVT VT =
Op.getValueType();
7957 struct ShuffleSourceInfo {
7959 unsigned MinElt = std::numeric_limits<unsigned>::max();
7960 unsigned MaxElt = 0;
7970 int WindowScale = 1;
7972 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7980 for (
unsigned i = 0; i < NumElts; ++i) {
7995 SDValue SourceVec =
V.getOperand(0);
7997 if (Source == Sources.
end())
8001 unsigned EltNo =
V.getConstantOperandVal(1);
8008 if (Sources.
size() > 2)
8014 for (
auto &Source : Sources) {
8015 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8016 if (SrcEltTy.
bitsLT(SmallestEltTy))
8017 SmallestEltTy = SrcEltTy;
8019 unsigned ResMultiplier =
8027 for (
auto &Src : Sources) {
8028 EVT SrcVT = Src.ShuffleVec.getValueType();
8032 if (SrcVTSize == VTSize)
8041 if (SrcVTSize < VTSize) {
8042 if (2 * SrcVTSize != VTSize)
8048 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8052 if (SrcVTSize != 2 * VTSize)
8055 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8060 if (Src.MinElt >= NumSrcElts) {
8065 Src.WindowBase = -NumSrcElts;
8066 }
else if (Src.MaxElt < NumSrcElts) {
8080 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8083 Src.WindowBase = -Src.MinElt;
8090 for (
auto &Src : Sources) {
8091 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8092 if (SrcEltTy == SmallestEltTy)
8095 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8097 Src.WindowBase *= Src.WindowScale;
8102 for (
auto Src : Sources)
8103 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8111 if (
Entry.isUndef())
8120 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8123 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8127 int *LaneMask = &
Mask[i * ResMultiplier];
8129 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8130 ExtractBase += NumElts * (Src - Sources.begin());
8131 for (
int j = 0;
j < LanesDefined; ++
j)
8132 LaneMask[j] = ExtractBase + j;
8138 assert(Sources.size() <= 2 &&
"Too many sources!");
8141 for (
unsigned i = 0; i < Sources.size(); ++i)
8148 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8170 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8190 unsigned PFIndexes[4];
8191 for (
unsigned i = 0; i != 4; ++i) {
8195 PFIndexes[i] = M[i];
8199 unsigned PFTableIndex =
8200 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8202 unsigned Cost = (PFEntry >> 30);
8208 bool ReverseVEXT, isV_UNDEF;
8209 unsigned Imm, WhichResult;
8212 if (EltSize >= 32 ||
8219 else if (Subtarget->hasNEON() &&
8224 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8227 else if (Subtarget->hasMVEIntegerOps() &&
8231 else if (Subtarget->hasMVEIntegerOps() &&
8245 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8246 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8247 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8250 if (LHSID == (1*9+2)*9+3)
return LHS;
8251 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8265 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8268 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8271 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8276 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8281 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8308 for (
int I : ShuffleMask)
8312 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8,
V1,
8315 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8,
V1, V2,
8321 EVT VT =
Op.getValueType();
8323 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8324 "Expect an v8i16/v16i8 type");
8330 std::vector<int> NewMask;
8334 NewMask.push_back(i);
8364 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8374 if (VT != MVT::v16i1)
8375 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8390 EVT VT =
Op.getValueType();
8394 assert(ST->hasMVEIntegerOps() &&
8395 "No support for vector shuffle of boolean predicates");
8405 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8421 "Expected identical vector type in expanded i1 shuffle!");
8425 PredAsVector2, ShuffleMask);
8430 if (VT == MVT::v2i1) {
8431 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8434 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8436 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8447 EVT VT =
Op.getValueType();
8451 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8452 "Unexpected vector type");
8454 int QuarterSize = NumElts / 4;
8463 for (
int i = 0; i <
Length; i++) {
8464 if (ShuffleMask[Start + i] >= 0) {
8465 if (ShuffleMask[Start + i] %
Length != i)
8467 MovIdx = ShuffleMask[Start + i] /
Length;
8475 for (
int i = 1; i <
Length; i++) {
8476 if (ShuffleMask[Start + i] >= 0 &&
8477 (ShuffleMask[Start + i] /
Length != MovIdx ||
8478 ShuffleMask[Start + i] %
Length != i))
8484 for (
int Part = 0; Part < 4; ++Part) {
8486 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8500 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8505 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8507 for (
int Part = 0; Part < 4; ++Part)
8508 for (
int i = 0; i < QuarterSize; i++)
8510 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8512 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8515 for (
int Part = 0; Part < 4; ++Part)
8531 EVT VT =
Op.getValueType();
8543 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8547 if (Mask[i] != i + BaseOffset) {
8548 if (OffElement == -1)
8554 return NonUndef > 2 && OffElement != -1;
8558 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8560 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8571 ShuffleMask[OffElement] < (
int)NumElts ?
V1 : V2,
8582 EVT VT =
Op.getValueType();
8586 if (ST->hasMVEIntegerOps() && EltSize == 1)
8597 if (EltSize <= 32) {
8601 if (Lane == -1) Lane = 0;
8605 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8612 bool IsScalarToVector =
true;
8613 for (
unsigned i = 1, e =
V1.getNumOperands(); i != e; ++i)
8614 if (!
V1.getOperand(i).isUndef()) {
8615 IsScalarToVector =
false;
8618 if (IsScalarToVector)
8619 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8621 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
V1,
8625 bool ReverseVEXT =
false;
8627 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8630 return DAG.
getNode(ARMISD::VEXT, dl, VT,
V1, V2,
8635 return DAG.
getNode(ARMISD::VREV64, dl, VT,
V1);
8637 return DAG.
getNode(ARMISD::VREV32, dl, VT,
V1);
8639 return DAG.
getNode(ARMISD::VREV16, dl, VT,
V1);
8651 unsigned WhichResult = 0;
8652 bool isV_UNDEF =
false;
8653 if (ST->hasNEON()) {
8655 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8662 if (ST->hasMVEIntegerOps()) {
8664 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2,
V1,
8667 return DAG.
getNode(ARMISD::VMOVN, dl, VT,
V1, V2,
8697 }) &&
"Unexpected shuffle index into UNDEF operand!");
8700 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8703 assert((WhichResult == 0) &&
8704 "In-place shuffle of concat can only have one result!");
8713 if (ST->hasMVEIntegerOps() && EltSize <= 32 &&
8714 (ST->hasFullFP16() || VT != MVT::v8f16)) {
8718 for (
bool Top : {
false,
true}) {
8719 for (
bool SingleSource : {
false,
true}) {
8720 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8725 SingleSource ?
V1 : V2);
8741 unsigned PFIndexes[4];
8742 for (
unsigned i = 0; i != 4; ++i) {
8743 if (ShuffleMask[i] < 0)
8746 PFIndexes[i] = ShuffleMask[i];
8750 unsigned PFTableIndex =
8751 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8753 unsigned Cost = (PFEntry >> 30);
8759 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8760 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8770 if (EltSize >= 32) {
8778 for (
unsigned i = 0; i < NumElts; ++i) {
8779 if (ShuffleMask[i] < 0)
8783 ShuffleMask[i] < (
int)NumElts ?
V1 : V2,
8791 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8795 if (ST->hasNEON() && VT == MVT::v8i8)
8799 if (ST->hasMVEIntegerOps())
8804 if (VT == MVT::v8f16 && !ST->hasFullFP16()) {
8806 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(0));
8808 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(1));
8810 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuf);
8818 EVT VecVT =
Op.getOperand(0).getValueType();
8821 assert(ST->hasMVEIntegerOps() &&
8822 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8825 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8826 unsigned Lane =
Op.getConstantOperandVal(2);
8827 unsigned LaneWidth =
8829 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8834 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8847 if (Subtarget->hasMVEIntegerOps() &&
8848 Op.getValueType().getScalarSizeInBits() == 1)
8872 IVecIn, IElt, Lane);
8881 EVT VecVT =
Op.getOperand(0).getValueType();
8884 assert(ST->hasMVEIntegerOps() &&
8885 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8888 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8889 unsigned Lane =
Op.getConstantOperandVal(1);
8890 unsigned LaneWidth =
8912 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8921 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8922 "Unexpected custom CONCAT_VECTORS lowering");
8924 "Unexpected custom CONCAT_VECTORS lowering");
8925 assert(ST->hasMVEIntegerOps() &&
8926 "CONCAT_VECTORS lowering only supported for MVE");
8929 EVT Op1VT =
V1.getValueType();
8930 EVT Op2VT = V2.getValueType();
8931 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8932 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8933 "Unexpected i1 concat operations!");
8946 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8951 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8960 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8961 EVT NewVT = NewV.getValueType();
8962 EVT ConcatVT = ConVec.getValueType();
8963 unsigned ExtScale = 1;
8964 if (NewVT == MVT::v2f64) {
8965 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8978 ConVec = ExtractInto(NewV1, ConVec, j);
8979 ConVec = ExtractInto(NewV2, ConVec, j);
8983 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8989 while (ConcatOps.
size() > 1) {
8990 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8993 ConcatOps[
I / 2] = ConcatPair(
V1, V2);
8997 return ConcatOps[0];
9002 EVT VT =
Op->getValueType(0);
9008 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9009 "unexpected CONCAT_VECTORS");
9030 EVT VT =
Op.getValueType();
9031 EVT Op1VT =
V1.getValueType();
9036 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9037 assert(ST->hasMVEIntegerOps() &&
9038 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9048 EVT SubVT = MVT::v4i32;
9050 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9060 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
9065 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9074 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9081 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9082 EVT VT =
N->getValueType(0);
9083 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9084 "Expected a vector i1 type!");
9086 EVT FromVT =
Op.getValueType();
9097 if (!Subtarget->hasMVEIntegerOps())
9100 EVT ToVT =
N->getValueType(0);
9143 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9145 EVT FromVT =
N->getOperand(0).getValueType();
9146 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9157 if (!Subtarget->hasMVEIntegerOps())
9162 EVT ToVT =
N->getValueType(0);
9163 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9166 EVT FromVT =
Op.getValueType();
9167 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9181 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9182 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9194 EVT VT =
N->getValueType(0);
9196 SDNode *BVN =
N->getOperand(0).getNode();
9201 unsigned HiElt = 1 - LoElt;
9206 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9222 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9223 SDNode *Elt =
N->getOperand(i).getNode();
9226 unsigned HalfSize = EltSize / 2;
9228 if (!
isIntN(HalfSize,
C->getSExtValue()))
9231 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9270 switch (OrigSimpleTy) {
9286 unsigned ExtOpcode) {
9309 if (ExtendedTy == LD->getMemoryVT())
9310 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9311 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9312 LD->getMemOperand()->getFlags());
9318 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9319 LD->getMemoryVT(), LD->getAlign(),
9320 LD->getMemOperand()->getFlags());
9333 N->getOperand(0)->getValueType(0),
9339 "Expected extending load");
9345 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9354 SDNode *BVN =
N->getOperand(0).getNode();
9356 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9364 EVT VT =
N->getValueType(0);
9370 for (
unsigned i = 0; i != NumElts; ++i) {
9371 const APInt &CInt =
N->getConstantOperandAPInt(i);
9380 unsigned Opcode =
N->getOpcode();
9382 SDNode *N0 =
N->getOperand(0).getNode();
9383 SDNode *N1 =
N->getOperand(1).getNode();
9391 unsigned Opcode =
N->getOpcode();
9393 SDNode *N0 =
N->getOperand(0).getNode();
9394 SDNode *N1 =
N->getOperand(1).getNode();
9404 EVT VT =
Op.getValueType();
9406 "unexpected type for custom-lowering ISD::MUL");
9407 SDNode *N0 =
Op.getOperand(0).getNode();
9408 SDNode *N1 =
Op.getOperand(1).getNode();
9409 unsigned NewOpc = 0;
9413 if (isN0SExt && isN1SExt)
9414 NewOpc = ARMISD::VMULLs;
9418 if (isN0ZExt && isN1ZExt)
9419 NewOpc = ARMISD::VMULLu;
9420 else if (isN1SExt || isN1ZExt) {
9424 NewOpc = ARMISD::VMULLs;
9427 NewOpc = ARMISD::VMULLu;
9431 NewOpc = ARMISD::VMULLu;
9437 if (VT == MVT::v2i64)
9454 "unexpected types for extended operands to VMULL");
9455 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9490 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9524 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9527 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9548 EVT VT =
Op.getValueType();
9549 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9550 "unexpected type for custom-lowering ISD::SDIV");
9557 if (VT == MVT::v8i8) {
9585 EVT VT =
Op.getValueType();
9586 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9587 "unexpected type for custom-lowering ISD::UDIV");
9594 if (VT == MVT::v8i8) {
9633 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9636 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9640 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9660 unsigned Opcode,
bool IsSigned) {
9661 EVT VT0 =
Op.getValue(0).getValueType();
9662 EVT VT1 =
Op.getValue(1).getValueType();
9664 bool InvertCarry = Opcode == ARMISD::SUBE;
9684 EVT VT =
Op.getValueType();
9685 assert((VT == MVT::i32 || VT == MVT::i64) &&
9686 "unexpected type for custom lowering DIV");
9692 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9694 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9701 for (
auto AI : {1, 0}) {
9703 Args.emplace_back(Operand,
9720ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9728 const bool MinSize =
ST.hasMinSize();
9729 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9730 :
ST.hasDivideInARMMode();
9734 if (
N->getOperand(0).getValueType().isVector())
9739 if (!(MinSize && HasDivide))
9752 if (Divisor.
sgt(128))
9760 assert(
Op.getValueType() == MVT::i32 &&
9761 "unexpected type for custom lowering DIV");
9764 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9767 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9773 if (
N->getValueType(0) == MVT::i32)
9774 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9777 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9781void ARMTargetLowering::ExpandDIV_Windows(
9786 assert(
Op.getValueType() == MVT::i64 &&
9787 "unexpected type for custom lowering DIV");
9802std::pair<SDValue, SDValue>
9803ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9809 EVT MemVT =
LD->getMemoryVT();
9810 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9814 unsigned AS =
LD->getAddressSpace();
9815 Align Alignment =
LD->getAlign();
9817 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9820 Alignment <= llvm::Align(2)) {
9823 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9829 Opts, dl,
LD->getChain());
9854 EVT MemVT =
ST->getMemoryVT();
9855 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9859 unsigned AS =
ST->getAddressSpace();
9860 Align Alignment =
ST->getAlign();
9862 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9865 Alignment <= llvm::Align(2)) {
9871 if (
ST->isTruncatingStore())
9875 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9879 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9880 dl,
ST->getChain());
9882 return CallResult.second;
9893 EVT MemVT = LD->getMemoryVT();
9894 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9895 MemVT == MVT::v16i1) &&
9896 "Expected a predicate type!");
9897 assert(MemVT ==
Op.getValueType());
9899 "Expected a non-extending load");
9900 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9914 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9916 LD->getMemOperand());
9922 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9923 if (MemVT != MVT::v16i1)
9932 EVT MemVT =
LD->getMemoryVT();
9934 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9935 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9936 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9937 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9940 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9941 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9946 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9947 auto Pair = LowerAEABIUnalignedLoad(
SDValue(
N, 0), DAG);
9949 Results.push_back(Pair.first);
9950 Results.push_back(Pair.second);
9957 EVT MemVT = ST->getMemoryVT();
9958 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9959 MemVT == MVT::v16i1) &&
9960 "Expected a predicate type!");
9961 assert(MemVT == ST->getValue().getValueType());
9962 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9963 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9968 SDValue Build = ST->getValue();
9969 if (MemVT != MVT::v16i1) {
9982 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9988 ST->getChain(), dl, GRP, ST->getBasePtr(),
9990 ST->getMemOperand());
9996 EVT MemVT =
ST->getMemoryVT();
9998 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9999 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
10000 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10001 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10002 SDNode *
N =
Op.getNode();
10015 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10016 MemVT,
ST->getMemOperand());
10017 }
else if (Subtarget->hasMVEIntegerOps() &&
10018 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10019 MemVT == MVT::v16i1))) {
10021 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
10022 return LowerAEABIUnalignedStore(
Op, DAG);
10029 (
N->getOpcode() == ARMISD::VMOVIMM &&
10035 MVT VT =
Op.getSimpleValueType();
10037 SDValue PassThru =
N->getPassThru();
10048 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10049 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10050 N->getExtensionType(),
N->isExpandingLoad());
10053 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
10055 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10062 if (!ST->hasMVEIntegerOps())
10066 unsigned BaseOpcode = 0;
10067 switch (
Op->getOpcode()) {
10083 unsigned NumActiveLanes = NumElts;
10085 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10086 NumActiveLanes == 2) &&
10087 "Only expected a power 2 vector size");
10091 while (NumActiveLanes > 4) {
10092 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10094 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10095 NumActiveLanes /= 2;
10099 if (NumActiveLanes == 4) {
10109 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10110 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10111 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10117 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10121 if (EltVT !=
Op->getValueType(0))
10128 if (!ST->hasMVEFloatOps())
10135 if (!ST->hasNEON())
10143 unsigned PairwiseIntrinsic = 0;
10144 switch (
Op->getOpcode()) {
10148 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10151 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10154 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10157 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10163 unsigned NumActiveLanes = NumElts;
10165 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10166 NumActiveLanes == 2) &&
10167 "Only expected a power 2 vector size");
10173 VT =
Lo.getValueType();
10175 NumActiveLanes /= 2;
10179 while (NumActiveLanes > 1) {
10181 NumActiveLanes /= 2;
10188 if (EltVT !=
Op.getValueType()) {
10189 unsigned Extend = 0;
10190 switch (
Op->getOpcode()) {
10202 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10247 const SDValue Ops[] = {RegClass, V0, SubReg0,
V1, SubReg1};
10253 SDLoc dl(V.getNode());
10254 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10264 assert(
N->getValueType(0) == MVT::i64 &&
10265 "AtomicCmpSwap on types less than 64 should be legal");
10274 ARM::CMP_SWAP_64,
SDLoc(
N),
10275 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10294 EVT VT =
Op.getValueType();
10303 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10305 Chain, IsSignaling);
10306 if (!
RHS.getNode()) {
10322 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10324 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10325 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10342 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10345 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10358 if (!IsSigned && Subtarget->isThumb1Only()) {
10376 Sub1Result, Sub1Result, Flags1);
10391 if (
Op.getValueType() != MVT::i32)
10405 unsigned Opcode = ARMISD::SUBC;
10414 bool CanUseAdd =
false;
10430 Opcode = ARMISD::ADDC;
10454 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10455 GTCondValue, Flags);
10459 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10460 LTCondValue, Flags);
10462 if (
Op.getValueType() != MVT::i32)
10470 switch (
Op.getOpcode()) {
10502 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10506 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10507 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10529 return LowerSET_FPMODE(
Op, DAG);
10531 return LowerRESET_FPMODE(
Op, DAG);
10535 !
Op.getValueType().isVector())
10536 return LowerDIV_Windows(
Op, DAG,
true);
10540 !
Op.getValueType().isVector())
10541 return LowerDIV_Windows(
Op, DAG,
false);
10557 return LowerALUO(
Op, DAG);
10565 EVT MemVT = LD->getMemoryVT();
10566 if (Subtarget->hasMVEIntegerOps() &&
10567 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10568 MemVT == MVT::v16i1))
10571 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10577 return LowerSTORE(
Op, DAG, Subtarget);
10602 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10611 return LowerSPONENTRY(
Op, DAG);
10613 return LowerFP_TO_BF16(
Op, DAG);
10614 case ARMISD::WIN__DBZCHK:
return SDValue();
10617 return LowerCMP(
Op, DAG);
10619 return LowerABS(
Op, DAG);
10624 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10625 Op.getOperand(1).getValueType() == MVT::bf16) &&
10626 "Expected custom lowering of rounding operations only for f16");
10629 {
Op.getOperand(0),
Op.getOperand(1)});
10630 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10631 {Ext.getValue(1), Ext.getValue(0)});
10638 unsigned IntNo =
N->getConstantOperandVal(0);
10640 if (IntNo == Intrinsic::arm_smlald)
10641 Opc = ARMISD::SMLALD;
10642 else if (IntNo == Intrinsic::arm_smlaldx)
10643 Opc = ARMISD::SMLALDX;
10644 else if (IntNo == Intrinsic::arm_smlsld)
10645 Opc = ARMISD::SMLSLD;
10646 else if (IntNo == Intrinsic::arm_smlsldx)
10647 Opc = ARMISD::SMLSLDX;
10653 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10657 N->getOperand(1),
N->getOperand(2),
10669 switch (
N->getOpcode()) {
10676 Res = ExpandBITCAST(
N, DAG, Subtarget);
10685 Res = LowerREM(
N, DAG);
10689 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10706 "can only expand DIV on Windows");
10718 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10747 "ROPI/RWPI not currently supported with SjLj");
10756 bool isThumb = Subtarget->isThumb();
10757 bool isThumb2 = Subtarget->
isThumb2();
10760 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10766 : &ARM::GPRRegClass;
10872 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10875 MachineRegisterInfo *MRI = &MF->
getRegInfo();
10879 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10880 : &ARM::GPRnopcRegClass;
10884 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10885 unsigned MaxCSNum = 0;
10886 for (MachineBasicBlock &BB : *MF) {
10892 for (MachineInstr &
II : BB) {
10893 if (!
II.isEHLabel())
10896 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10897 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10899 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10900 for (
unsigned Idx : CallSiteIdxs) {
10901 CallSiteNumToLPad[Idx].push_back(&BB);
10902 MaxCSNum = std::max(MaxCSNum, Idx);
10909 std::vector<MachineBasicBlock*> LPadList;
10910 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10911 LPadList.reserve(CallSiteNumToLPad.
size());
10912 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10913 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10914 for (MachineBasicBlock *
MBB : MBBList) {
10915 LPadList.push_back(
MBB);
10920 assert(!LPadList.empty() &&
10921 "No landing pad destinations for the dispatch jump table!");
10924 MachineJumpTableInfo *JTI =
10931 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10934 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10936 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10939 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10943 MF->insert(MF->end(), DispatchBB);
10944 MF->insert(MF->end(), DispContBB);
10945 MF->insert(MF->end(), TrapBB);
10949 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10951 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10955 MachineInstrBuilder MIB;
10956 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10958 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10968 unsigned NumLPads = LPadList.size();
10969 if (Subtarget->isThumb2()) {
10971 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10977 if (NumLPads < 256) {
10978 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10980 .
addImm(LPadList.size())
10984 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10985 .
addImm(NumLPads & 0xFFFF)
10988 unsigned VReg2 = VReg1;
10989 if ((NumLPads & 0xFFFF0000) != 0) {
10991 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10997 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11003 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11009 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11014 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11021 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11025 }
else if (Subtarget->isThumb()) {
11027 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11033 if (NumLPads < 256) {
11034 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11039 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11041 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11044 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11045 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11048 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11052 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11058 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11064 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11071 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11076 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11082 MachineMemOperand *JTMMOLd =
11087 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11093 unsigned NewVReg6 = NewVReg5;
11094 if (IsPositionIndependent) {
11096 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11103 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11108 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11114 if (NumLPads < 256) {
11115 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11119 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11121 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11122 .
addImm(NumLPads & 0xFFFF)
11125 unsigned VReg2 = VReg1;
11126 if ((NumLPads & 0xFFFF0000) != 0) {
11128 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11134 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11139 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11141 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11144 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11145 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11148 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11153 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11165 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11171 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11175 MachineMemOperand *JTMMOLd =
11179 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11186 if (IsPositionIndependent) {
11187 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11192 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11199 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11200 for (MachineBasicBlock *CurMBB : LPadList) {
11201 if (SeenMBBs.
insert(CurMBB).second)
11208 for (MachineBasicBlock *BB : InvokeBBs) {
11212 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11213 while (!Successors.empty()) {
11214 MachineBasicBlock *SMBB = Successors.pop_back_val();
11216 BB->removeSuccessor(SMBB);
11222 BB->normalizeSuccProbs();
11229 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11230 if (!
II->isCall())
continue;
11232 DenseSet<unsigned> DefRegs;
11234 OI =
II->operands_begin(), OE =
II->operands_end();
11236 if (!OI->isReg())
continue;
11237 DefRegs.
insert(OI->getReg());
11240 MachineInstrBuilder MIB(*MF, &*
II);
11242 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11243 unsigned Reg = SavedRegs[i];
11244 if (Subtarget->isThumb2() &&
11245 !ARM::tGPRRegClass.contains(
Reg) &&
11246 !ARM::hGPRRegClass.contains(
Reg))
11248 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11250 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11262 for (MachineBasicBlock *MBBLPad : MBBLPads)
11263 MBBLPad->setIsEHPad(
false);
11266 MI.eraseFromParent();
11279static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11281 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11282 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11284 return LdSize == 4 ? ARM::tLDRi
11285 : LdSize == 2 ? ARM::tLDRHi
11286 : LdSize == 1 ? ARM::tLDRBi : 0;
11288 return LdSize == 4 ? ARM::t2LDR_POST
11289 : LdSize == 2 ? ARM::t2LDRH_POST
11290 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11291 return LdSize == 4 ? ARM::LDR_POST_IMM
11292 : LdSize == 2 ? ARM::LDRH_POST
11293 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11298static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11300 return StSize == 16 ? ARM::VST1q32wb_fixed
11301 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11303 return StSize == 4 ? ARM::tSTRi
11304 : StSize == 2 ? ARM::tSTRHi
11305 : StSize == 1 ? ARM::tSTRBi : 0;
11307 return StSize == 4 ? ARM::t2STR_POST
11308 : StSize == 2 ? ARM::t2STRH_POST
11309 : StSize == 1 ? ARM::t2STRB_POST : 0;
11310 return StSize == 4 ? ARM::STR_POST_IMM
11311 : StSize == 2 ? ARM::STRH_POST
11312 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11319 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11320 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11321 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11322 assert(LdOpc != 0 &&
"Should have a load opcode");
11329 }
else if (IsThumb1) {
11335 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11340 }
else if (IsThumb2) {
11360 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11361 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11362 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11363 assert(StOpc != 0 &&
"Should have a store opcode");
11365 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11370 }
else if (IsThumb1) {
11377 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11382 }
else if (IsThumb2) {
11383 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11389 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11404 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11410 unsigned SizeVal =
MI.getOperand(2).getImm();
11411 unsigned Alignment =
MI.getOperand(3).getImm();
11415 MachineRegisterInfo &MRI = MF->
getRegInfo();
11416 unsigned UnitSize = 0;
11417 const TargetRegisterClass *TRC =
nullptr;
11418 const TargetRegisterClass *VecTRC =
nullptr;
11420 bool IsThumb1 = Subtarget->isThumb1Only();
11421 bool IsThumb2 = Subtarget->isThumb2();
11422 bool IsThumb = Subtarget->isThumb();
11424 if (Alignment & 1) {
11426 }
else if (Alignment & 2) {
11431 Subtarget->hasNEON()) {
11432 if ((Alignment % 16 == 0) && SizeVal >= 16)
11434 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11443 bool IsNeon = UnitSize >= 8;
11444 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11446 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11447 : UnitSize == 8 ? &ARM::DPRRegClass
11450 unsigned BytesLeft = SizeVal % UnitSize;
11451 unsigned LoopSize = SizeVal - BytesLeft;
11453 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11457 unsigned srcIn = src;
11458 unsigned destIn = dest;
11459 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11464 IsThumb1, IsThumb2);
11466 IsThumb1, IsThumb2);
11474 for (
unsigned i = 0; i < BytesLeft; i++) {
11479 IsThumb1, IsThumb2);
11481 IsThumb1, IsThumb2);
11485 MI.eraseFromParent();
11511 MF->
insert(It, loopMBB);
11512 MF->
insert(It, exitMBB);
11515 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11526 if (Subtarget->useMovt()) {
11527 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11530 }
else if (Subtarget->genExecuteOnly()) {
11531 assert(IsThumb &&
"Non-thumb expected to have used movt");
11536 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11540 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11541 MachineMemOperand *CPMMO =
11565 MachineBasicBlock *entryBB = BB;
11580 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11588 IsThumb1, IsThumb2);
11590 IsThumb1, IsThumb2);
11594 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11600 MachineInstrBuilder MIB =
11602 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11611 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11620 auto StartOfExit = exitMBB->
begin();
11624 unsigned srcIn = srcLoop;
11625 unsigned destIn = destLoop;
11626 for (
unsigned i = 0; i < BytesLeft; i++) {
11630 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11631 IsThumb1, IsThumb2);
11632 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11633 IsThumb1, IsThumb2);
11638 MI.eraseFromParent();
11646 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11649 assert(TM.getTargetTriple().isOSWindows() &&
11650 "__chkstk is only supported on Windows");
11651 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11671 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11672 if (ChkStkLibcall == RTLIB::Unsupported)
11676 switch (TM.getCodeModel()) {
11718 MI.eraseFromParent();
11727 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11742 .
addReg(
MI.getOperand(0).getReg())
11750 MI.eraseFromParent();
11774 if (miI == BB->
end()) {
11776 if (Succ->isLiveIn(ARM::CPSR))
11782 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11795 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11802 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11809 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11812 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11813 .
addUse(TotalIterationsReg)
11820 return TotalIterationsReg;
11831 Register TotalIterationsReg,
bool IsMemcpy) {
11840 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11850 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11858 Register RemainingLoopIterationsReg =
11860 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11861 .
addUse(TotalIterationsReg)
11863 .
addUse(RemainingLoopIterationsReg)
11869 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11870 .
addUse(ElementCountReg)
11872 .
addUse(RemainingElementsReg)
11877 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11878 .
addUse(PredCounterPhiReg)
11883 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11884 .
addUse(PredCounterPhiReg)
11893 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11902 SrcValueReg = OpSrcReg;
11904 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11915 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11916 .
addUse(LoopCounterPhiReg)
11919 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11920 .
addUse(RemainingLoopIterationsReg)
11938 "Invalid call instruction for a KCFI check");
11941 switch (
MBBI->getOpcode()) {
11944 case ARM::BLX_pred:
11945 case ARM::BLX_noip:
11946 case ARM::BLX_pred_noip:
11948 TargetOp = &
MBBI->getOperand(0);
11950 case ARM::TCRETURNri:
11951 case ARM::TCRETURNrinotr12:
11952 case ARM::TAILJMPr:
11953 case ARM::TAILJMPr4:
11954 TargetOp = &
MBBI->getOperand(0);
11960 case ARM::tBLXr_noip:
11961 case ARM::tBX_CALL:
11962 TargetOp = &
MBBI->getOperand(2);
11965 case ARM::tTAILJMPr:
11966 TargetOp = &
MBBI->getOperand(0);
11972 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11976 unsigned KCFICheckOpcode;
11977 if (Subtarget->isThumb()) {
11978 if (Subtarget->isThumb2()) {
11979 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11981 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11984 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11998 bool isThumb2 = Subtarget->isThumb2();
11999 switch (
MI.getOpcode()) {
12006 case ARM::tLDR_postidx: {
12010 .
add(
MI.getOperand(2))
12011 .
add(
MI.getOperand(3))
12012 .
add(
MI.getOperand(4))
12013 .
add(
MI.getOperand(0))
12015 MI.eraseFromParent();
12019 case ARM::MVE_MEMCPYLOOPINST:
12020 case ARM::MVE_MEMSETLOOPINST: {
12050 Register OpDestReg =
MI.getOperand(0).getReg();
12051 Register OpSrcReg =
MI.getOperand(1).getReg();
12052 Register OpSizeReg =
MI.getOperand(2).getReg();
12072 if (TpExit == BB) {
12074 "block containing memcpy/memset Pseudo");
12084 genTPEntry(TpEntry, TpLoopBody, TpExit, OpSizeReg,
TII, dl, MRI);
12087 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12089 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12092 Properties.resetNoPHIs();
12104 MI.eraseFromParent();
12114 case ARM::t2STR_preidx:
12115 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12117 case ARM::t2STRB_preidx:
12118 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12120 case ARM::t2STRH_preidx:
12121 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12124 case ARM::STRi_preidx:
12125 case ARM::STRBi_preidx: {
12126 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12127 : ARM::STRB_PRE_IMM;
12129 unsigned Offset =
MI.getOperand(4).getImm();
12137 .
add(
MI.getOperand(0))
12138 .
add(
MI.getOperand(1))
12139 .
add(
MI.getOperand(2))
12141 .
add(
MI.getOperand(5))
12142 .
add(
MI.getOperand(6))
12144 MI.eraseFromParent();
12147 case ARM::STRr_preidx:
12148 case ARM::STRBr_preidx:
12149 case ARM::STRH_preidx: {
12151 switch (
MI.getOpcode()) {
12153 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12154 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12155 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12160 MI.eraseFromParent();
12164 case ARM::tMOVCCr_pseudo: {
12182 F->insert(It, copy0MBB);
12183 F->insert(It, sinkMBB);
12186 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12192 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12208 .
addImm(
MI.getOperand(3).getImm())
12209 .
addReg(
MI.getOperand(4).getReg());
12224 .
addReg(
MI.getOperand(1).getReg())
12226 .
addReg(
MI.getOperand(2).getReg())
12229 MI.eraseFromParent();
12234 case ARM::BCCZi64: {
12240 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12245 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12249 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12255 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12259 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12269 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12278 MI.eraseFromParent();
12282 case ARM::Int_eh_sjlj_setjmp:
12283 case ARM::Int_eh_sjlj_setjmp_nofp:
12284 case ARM::tInt_eh_sjlj_setjmp:
12285 case ARM::t2Int_eh_sjlj_setjmp:
12286 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12289 case ARM::Int_eh_sjlj_setup_dispatch:
12290 EmitSjLjDispatchBlock(
MI, BB);
12292 case ARM::COPY_STRUCT_BYVAL_I32:
12294 return EmitStructByval(
MI, BB);
12295 case ARM::WIN__CHKSTK:
12296 return EmitLowered__chkstk(
MI, BB);
12297 case ARM::WIN__DBZCHK:
12298 return EmitLowered__dbzchk(
MI, BB);
12314 if (!
Node->hasAnyUseOfValue(0)) {
12315 MI.getOperand(0).setIsDead(
true);
12317 if (!
Node->hasAnyUseOfValue(1)) {
12318 MI.getOperand(1).setIsDead(
true);
12322 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12324 : &ARM::GPRRegClass);
12331 if (
MI.getOpcode() == ARM::MEMCPY) {
12352 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12353 &&
"converted opcode should be the same except for cc_out"
12354 " (and, on Thumb1, pred)");
12362 if (Subtarget->isThumb1Only()) {
12363 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12364 MI.addOperand(
MI.getOperand(1));
12365 MI.removeOperand(1);
12369 for (
unsigned i =
MI.getNumOperands(); i--;) {
12371 if (
op.isReg() &&
op.isUse()) {
12374 MI.tieOperands(DefIdx, i);
12382 ccOutIdx =
MCID->getNumOperands() - 1;
12384 ccOutIdx =
MCID->getNumOperands() - 1;
12388 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12389 assert(!NewOpc &&
"Optional cc_out operand required");
12394 bool definesCPSR =
false;
12395 bool deadCPSR =
false;
12396 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12400 definesCPSR =
true;
12403 MI.removeOperand(i);
12407 if (!definesCPSR) {
12408 assert(!NewOpc &&
"Optional cc_out operand required");
12411 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12413 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12414 "expect uninitialized optional cc_out operand");
12416 if (!Subtarget->isThumb1Only())
12452 switch (
N->getOpcode()) {
12453 default:
return false;
12455 CC =
N->getOperand(0);
12477 EVT VT =
N->getValueType(0);
12478 CC =
N->getOperand(0);
12525 EVT VT =
N->getValueType(0);
12528 bool SwapSelectOps;
12530 NonConstantVal, DAG))
12536 OtherOp, NonConstantVal);
12542 CCOp, TrueVal, FalseVal);
12562 if (
N->getOpcode() == ARMISD::VUZP)
12566 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12581 if (!
N->getValueType(0).is64BitVector())
12589 EVT VT =
N->getValueType(0);
12628 EVT VT =
N->getValueType(0);
12634 Opcode = Intrinsic::arm_neon_vpaddls;
12636 Opcode = Intrinsic::arm_neon_vpaddlu;
12664 EVT VT =
N->getValueType(0);
12679 unsigned nextIndex = 0;
12730 Ops.push_back(Vec);
12747 return DAG.
getNode(ExtOp, dl, VT, tmp);
12778 if (SRA.getOpcode() !=
ISD::SRA) {
12785 if (Const->getZExtValue() != 31)
12790 if (SRA.getOperand(0) !=
Mul)
12794 SDLoc dl(AddcNode);
12795 unsigned Opcode = 0;
12800 Opcode = ARMISD::SMLALBB;
12801 Op0 =
Mul.getOperand(0);
12802 Op1 =
Mul.getOperand(1);
12804 Opcode = ARMISD::SMLALBT;
12805 Op0 =
Mul.getOperand(0);
12806 Op1 =
Mul.getOperand(1).getOperand(0);
12808 Opcode = ARMISD::SMLALTB;
12809 Op0 =
Mul.getOperand(0).getOperand(0);
12810 Op1 =
Mul.getOperand(1);
12812 Opcode = ARMISD::SMLALTT;
12813 Op0 =
Mul->getOperand(0).getOperand(0);
12814 Op1 =
Mul->getOperand(1).getOperand(0);
12830 SDValue resNode(AddcNode, 0);
12858 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12859 "Expect an ADDE or SUBE");
12863 "ADDE node has the wrong inputs");
12867 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12868 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12869 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12870 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12882 "Expect ADDC with two result values. First: i32");
12886 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12902 bool IsLeftOperandMUL =
false;
12907 IsLeftOperandMUL =
true;
12918 SDValue *LowAddSub =
nullptr;
12921 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12924 if (IsLeftOperandMUL)
12925 HiAddSub = &AddeSubeOp1;
12927 HiAddSub = &AddeSubeOp0;
12932 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12933 LoMul = &AddcSubcOp0;
12934 LowAddSub = &AddcSubcOp1;
12936 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12937 LoMul = &AddcSubcOp1;
12938 LowAddSub = &AddcSubcOp0;
12946 if (AddcSubcNode == HiAddSub->getNode() ||
12962 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12967 Ops.push_back(*HiAddSub);
12968 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12969 FinalOpc = ARMISD::SMMLSR;
12971 FinalOpc = ARMISD::SMMLAR;
12976 return SDValue(AddeSubeNode, 0);
12977 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12983 Ops.push_back(*LowAddSub);
12984 Ops.push_back(*HiAddSub);
12997 return SDValue(AddeSubeNode, 0);
13009 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13014 if (AddcNode->
getOpcode() != ARMISD::ADDC)
13018 SDNode *UmlalNode =
nullptr;
13057 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13062 SDNode* AddcNode =
N->getOperand(2).getNode();
13063 SDNode* AddeNode =
N->getOperand(3).getNode();
13064 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
13065 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
13071 {N->getOperand(0), N->getOperand(1),
13072 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13082 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13086 if (
LHS->getOpcode() == ARMISD::ADDE &&
13096 int32_t imm =
C->getSExtValue();
13097 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13100 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13102 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13117 int64_t imm =
C->getSExtValue();
13126 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13128 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13129 N->getOperand(0),
RHS,
N->getOperand(2));
13141 if (!Subtarget->hasMVEIntegerOps())
13154 SetCC =
N->getOperand(0);
13158 TrueVal =
N->getOperand(1);
13159 FalseVal =
N->getOperand(2);
13161 LHS =
N->getOperand(0);
13162 RHS =
N->getOperand(1);
13164 TrueVal =
N->getOperand(2);
13165 FalseVal =
N->getOperand(3);
13170 unsigned int Opcode = 0;
13174 Opcode = ARMISD::VMINVu;
13180 Opcode = ARMISD::VMINVs;
13186 Opcode = ARMISD::VMAXVu;
13192 Opcode = ARMISD::VMAXVs;
13199 switch (TrueVal->getOpcode()) {
13218 if (TrueVal !=
LHS || FalseVal !=
RHS)
13221 EVT LeftType =
LHS->getValueType(0);
13222 EVT RightType =
RHS->getValueType(0);
13225 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13229 if (VectorScalarType != MVT::i32)
13237 if (VectorScalarType != MVT::i32)
13250 EVT VT =
N->getValueType(0);
13258 Shft =
N->getOperand(0);
13265 Cmp.getOperand(0) !=
N->getOperand(1) ||
13266 Cmp.getOperand(1) !=
N->getOperand(2))
13268 Shft =
N->getOperand(1);
13280 ScalarType = MVT::i8;
13283 case (1 << 15) - 1:
13284 ScalarType = MVT::i16;
13287 case (1ULL << 31) - 1:
13288 ScalarType = MVT::i32;
13319 unsigned LegalLanes = 128 / (ShftAmt + 1);
13331 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13332 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13333 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13334 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13343 for (
unsigned I = 0;
I < NumParts; ++
I) {
13350 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13360 if (!Subtarget->hasMVEIntegerOps())
13365 if (
N->getOperand(0).getOpcode() == ARMISD::PREDICATE_CAST &&
13367 unsigned C =
N->getOperand(0).getConstantOperandVal(0);
13369 return N->getOperand(2);
13371 return N->getOperand(1);
13386 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13396 if (!Const || !Const->isOne())
13414 EVT VT =
N->getValueType(0);
13416 if (!Subtarget->hasMVEIntegerOps() ||
13445 Opc = Intrinsic::arm_mve_vctp64;
13448 Opc = Intrinsic::arm_mve_vctp32;
13451 Opc = Intrinsic::arm_mve_vctp16;
13454 Opc = Intrinsic::arm_mve_vctp8;
13508 EVT VT =
N->getValueType(0);
13514 switch (
Op.getOpcode()) {
13516 case ARMISD::VADDVs:
13517 case ARMISD::VADDVu:
13518 case ARMISD::VMLAVs:
13519 case ARMISD::VMLAVu:
13539 unsigned N0RedOp = 0;
13546 unsigned N1RedOp = 0;
13560 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13562 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13569 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13593 if (!BaseLocDecomp0.getBase() ||
13594 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13595 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13597 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13599 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13609 if (IsBefore < 0) {
13612 }
else if (IsBefore > 0) {
13625 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13635 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13645 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13647 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13654 if (!Subtarget->hasMVEIntegerOps())
13660 EVT VT =
N->getValueType(0);
13665 if (VT != MVT::i64)
13676 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13696 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13705 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13707 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13709 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13711 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13713 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13715 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13717 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13719 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13721 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13723 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13725 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13727 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13729 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13731 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13733 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13735 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13745 "Expected shift op");
13747 SDValue ShiftLHS =
N->getOperand(0);
13761 if (Subtarget->isThumb1Only()) {
13772 if (Const->getAPIntValue().ult(256))
13775 Const->getAPIntValue().sgt(-256))
13791 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13792 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13793 "Expected XOR(SHIFT) pattern");
13798 if (XorC && ShiftC) {
13799 unsigned MaskIdx, MaskLen;
13800 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13801 unsigned ShiftAmt = ShiftC->getZExtValue();
13802 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13803 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13804 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13805 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13815 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13817 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13818 "Expected shift-shift mask");
13820 if (!Subtarget->isThumb1Only())
13823 EVT VT =
N->getValueType(0);
13831 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13833 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13838 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps()) {
13839 if (Subtarget->isThumb1Only())
13853 return Subtarget->hasVFP2Base();
13855 return Subtarget->hasVFP2Base();
13857 return Subtarget->hasFP64();
13860 return Subtarget->hasMVEFloatOps();
13889 if (ST->isThumb() && ST->isThumb1Only())
13893 for (
auto *U :
N->users()) {
13894 switch(U->getOpcode()) {
13912 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13913 U->getOperand(1).getOpcode() ==
ISD::SHL)
13923 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13930 if (!C1ShlC2 || !C2)
13933 APInt C2Int = C2->getAPIntValue();
13934 APInt C1Int = C1ShlC2->getAPIntValue();
13936 if (C2Int.
uge(C2Width))
13942 if ((C1Int & Mask) != C1Int)
13949 auto LargeImm = [](
const APInt &Imm) {
13950 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13951 return Imm.getBitWidth() - Zeros > 8;
13954 if (LargeImm(C1Int) || LargeImm(C2Int))
13966 SHL.dump();
N->dump());
14027 if (
Op.hasOneUse() && ShiftAmt &&
14028 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
14086 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14107 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14128 if (!Subtarget->hasVMLxForwarding())
14147 EVT VT =
N->getValueType(0);
14158 EVT VT =
N->getValueType(0);
14159 if (VT != MVT::v2i64)
14170 return Op->getOperand(0);
14184 And =
And->getOperand(0);
14189 Mask = Mask->getOperand(0);
14192 Mask.getValueType() != MVT::v4i32)
14198 return And->getOperand(0);
14203 if (
SDValue Op0 = IsSignExt(N0)) {
14204 if (
SDValue Op1 = IsSignExt(N1)) {
14205 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14206 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14207 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14210 if (
SDValue Op0 = IsZeroExt(N0)) {
14211 if (
SDValue Op1 = IsZeroExt(N1)) {
14212 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14213 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14214 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14226 EVT VT =
N->getValueType(0);
14227 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14238 if (VT != MVT::i32)
14245 int64_t MulAmt =
C->getSExtValue();
14248 ShiftAmt = ShiftAmt & (32 - 1);
14253 MulAmt >>= ShiftAmt;
14314 if (
N->getValueType(0) != MVT::i32)
14323 if (C1 == 255 || C1 == 65535)
14326 SDNode *N0 =
N->getOperand(0).getNode();
14340 if (!C2 || C2 >= 32)
14384 if (Trailing == C2 && C2 + C3 < 32) {
14397 if (Leading == C2 && C2 + C3 < 32) {
14425 EVT VT =
N->getValueType(0);
14429 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14432 APInt SplatBits, SplatUndef;
14433 unsigned SplatBitSize;
14435 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14436 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14437 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14438 SplatBitSize == 64) {
14445 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14447 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14472 if (!Subtarget->hasV6Ops() ||
14473 (Subtarget->isThumb() &&
14474 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14477 SDValue SRL = OR->getOperand(0);
14478 SDValue SHL = OR->getOperand(1);
14481 SRL = OR->getOperand(1);
14482 SHL = OR->getOperand(0);
14489 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14493 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14494 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14495 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14514 unsigned Opcode = 0;
14515 if (
isS16(OpS16, DAG))
14516 Opcode = ARMISD::SMULWB;
14518 Opcode = ARMISD::SMULWT;
14533 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14536 EVT VT =
N->getValueType(0);
14551 if (VT != MVT::i32)
14564 if (Mask == 0xffff)
14571 if ((Val & ~Mask) != Val)
14577 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14596 (Mask == ~Mask2)) {
14599 if (Subtarget->hasDSP() &&
14600 (Mask == 0xffff || Mask == 0xffff0000))
14606 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14613 (~Mask == Mask2)) {
14616 if (Subtarget->hasDSP() &&
14617 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14673 if (
N->getOpcode() == ARMISD::VCMP)
14675 else if (
N->getOpcode() == ARMISD::VCMPZ)
14683 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14690 EVT VT =
N->getValueType(0);
14695 auto IsFreelyInvertable = [&](
SDValue V) {
14696 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14702 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14720 if (AndOp.getOpcode() !=
ISD::AND)
14724 SDValue Mask = AndOp.getOperand(1);
14734 bool IsShiftRight =
false;
14737 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14738 IsShiftRight =
true;
14741 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14749 APInt RequiredMask = IsShiftRight
14752 if (MaskBits != RequiredMask)
14755 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14765 EVT VT =
N->getValueType(0);
14771 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14772 VT == MVT::v8i1 || VT == MVT::v16i1))
14775 APInt SplatBits, SplatUndef;
14776 unsigned SplatBitSize;
14778 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14779 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14780 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14781 SplatBitSize == 64) {
14788 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14790 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14810 (Subtarget->hasMVEIntegerOps() &&
14811 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14814 return ShiftInsert;
14818 return ShiftInsert;
14832 unsigned SplatBitSize;
14835 APInt SplatBits0, SplatBits1;
14839 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14840 HasAnyUndefs) && !HasAnyUndefs) {
14841 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14842 HasAnyUndefs) && !HasAnyUndefs) {
14847 SplatBits0 == ~SplatBits1) {
14855 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14875 if (CSINC.
getOpcode() != ARMISD::CSINC)
14877 if (CSINC.
getOpcode() == ARMISD::CSINC &&
14890 EVT VT =
N->getValueType(0);
14905 if (Subtarget->hasMVEIntegerOps()) {
14933 assert(
N->getOpcode() == ARMISD::BFI);
14936 ToMask =
~N->getConstantOperandAPInt(2);
14956 unsigned LastActiveBitInA =
A.countr_zero();
14957 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14958 return LastActiveBitInA - 1 == FirstActiveBitInB;
14963 APInt ToMask, FromMask;
14968 if (V.getOpcode() != ARMISD::BFI)
14971 APInt NewToMask, NewFromMask;
14973 if (NewFrom != From)
14977 if ((NewToMask & ToMask).getBoolValue())
15002 unsigned InvMask =
N->getConstantOperandVal(2);
15006 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
15007 "undefined behavior");
15008 unsigned Mask = (1u << Width) - 1;
15010 if ((Mask & (~Mask2)) == 0)
15012 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
15019 APInt ToMask1, FromMask1;
15022 APInt ToMask2, FromMask2;
15028 APInt NewFromMask = FromMask1 | FromMask2;
15029 APInt NewToMask = ToMask1 | ToMask2;
15031 EVT VT =
N->getValueType(0);
15034 if (NewFromMask[0] == 0)
15037 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
15045 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
15046 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
15047 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
15049 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
15053 EVT VT =
N->getValueType(0);
15056 N->getOperand(1),
N->getOperand(2));
15068 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
15070 SDValue CSInc = Cmp->getOperand(0);
15080 if (CSInc.
getOpcode() == ARMISD::CSINC &&
15120 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15121 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15124 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15126 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15139 SDValue InDouble =
N->getOperand(0);
15140 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15154 SDValue BasePtr = LD->getBasePtr();
15156 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15157 LD->getAlign(), LD->getMemOperand()->getFlags());
15163 LD->getPointerInfo().getWithOffset(4),
15165 LD->getMemOperand()->getFlags());
15184 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15198 if (!Subtarget->
isLittle() && BVSwap)
15216 if (!Subtarget->
isLittle() && BVSwap)
15235 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15248 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15261 if (Copy.getValueType() == MVT::f32 &&
15263 bool HasGlue = Copy->getNumOperands() == 3;
15264 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15265 HasGlue ? Copy->getOperand(2) :
SDValue()};
15266 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15285 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15286 LN0->getMemoryVT() == MVT::i16) {
15289 LN0->getBasePtr(), LN0->getMemOperand());
15307 EVT VT =
N->getValueType(0);
15341 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15342 for (
unsigned i = 0; i < NumElts; ++i) {
15343 SDNode *Elt =
N->getOperand(i).getNode();
15360 if (
N->getNumOperands() == 2)
15366 EVT VT =
N->getValueType(0);
15372 for (
unsigned i = 0; i < NumElts; ++i) {
15398 EVT VT =
N->getValueType(0);
15406 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15411 Use->getValueType(0).isFloatingPoint())
15419 unsigned NumOfBitCastedElts = 0;
15421 unsigned NumOfRelevantElts = NumElts;
15422 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15427 ++NumOfBitCastedElts;
15431 --NumOfRelevantElts;
15435 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15453 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15458 V->getOperand(0).getValueType() == MVT::i32)
15460 V = V.getOperand(0);
15477 EVT VT =
N->getValueType(0);
15482 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15484 if (
Op->getOperand(0).getValueType() == VT)
15485 return Op->getOperand(0);
15486 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15493 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15500 if (
Op.getValueType() == MVT::i32) {
15511 EVT VT =
N->getValueType(0);
15516 if (ST->isLittle())
15520 if (
Op.getValueType() == VT)
15527 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15529 if (
Op->getOperand(0).getValueType() == VT)
15530 return Op->getOperand(0);
15531 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15539 if (!Subtarget->hasMVEIntegerOps())
15542 EVT VT =
N->getValueType(0);
15550 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15556 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15560 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15573 EVT VT =
N->getValueType(0);
15574 SDNode *Elt =
N->getOperand(1).getNode();
15589 Vec, V,
N->getOperand(2));
15599 EVT VT =
N->getValueType(0);
15627 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15628 isa<ConstantSDNode>(V->getOperand(1)) &&
15629 V->getConstantOperandVal(1) == Lane + 1 &&
15630 V->getOperand(0).getResNo() == ResNo;
15632 if (OtherIt == Op0->
users().
end())
15637 SDValue OtherExt(*OtherIt, 0);
15649 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15652 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15662 EVT VT =
N->getValueType(0);
15666 if (Op0->
getOpcode() == ARMISD::VDUP) {
15668 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15669 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15670 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15671 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15672 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15675 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15676 X =
X->getOperand(0);
15677 if (
X.getValueType() == VT)
15685 return Op0.
getOperand(
N->getConstantOperandVal(1));
15695 unsigned Offset =
N->getConstantOperandVal(1);
15697 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15707 unsigned Idx =
N->getConstantOperandVal(1);
15722 unsigned Lane =
N->getConstantOperandVal(1);
15750 EVT VT =
N->getValueType(0);
15753 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15755 Op.getOperand(0).getValueType().getScalarType())
15756 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15765 SDValue SubVec =
N->getOperand(1);
15766 uint64_t IdxVal =
N->getConstantOperandVal(2);
15777 if (IdxVal == 0 && Vec.
isUndef())
15783 (IdxVal != 0 && IdxVal != NumSubElts))
15814 ARMISD::VMOVN,
DL, VT,
15820 ARMISD::VMOVN,
DL, VT,
15856 EVT VT =
N->getValueType(0);
15867 unsigned HalfElts = NumElts/2;
15869 for (
unsigned n = 0; n < NumElts; ++n) {
15872 if (MaskElt < (
int)HalfElts)
15874 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15875 NewElt = HalfElts + MaskElt - NumElts;
15918 bool SimpleConstIncOnly,
15926 bool isLoadOp =
true;
15927 bool isLaneOp =
false;
15930 bool hasAlignment =
true;
15931 unsigned NewOpc = 0;
15932 unsigned NumVecs = 0;
15933 if (
Target.isIntrinsic) {
15934 unsigned IntNo =
N->getConstantOperandVal(1);
15938 case Intrinsic::arm_neon_vld1:
15942 case Intrinsic::arm_neon_vld2:
15946 case Intrinsic::arm_neon_vld3:
15950 case Intrinsic::arm_neon_vld4:
15954 case Intrinsic::arm_neon_vld1x2:
15957 hasAlignment =
false;
15959 case Intrinsic::arm_neon_vld1x3:
15962 hasAlignment =
false;
15964 case Intrinsic::arm_neon_vld1x4:
15967 hasAlignment =
false;
15969 case Intrinsic::arm_neon_vld2dup:
15973 case Intrinsic::arm_neon_vld3dup:
15977 case Intrinsic::arm_neon_vld4dup:
15981 case Intrinsic::arm_neon_vld2lane:
15986 case Intrinsic::arm_neon_vld3lane:
15991 case Intrinsic::arm_neon_vld4lane:
15996 case Intrinsic::arm_neon_vst1:
16001 case Intrinsic::arm_neon_vst2:
16002 NewOpc = ARMISD::VST2_UPD;
16006 case Intrinsic::arm_neon_vst3:
16011 case Intrinsic::arm_neon_vst4:
16012 NewOpc = ARMISD::VST4_UPD;
16016 case Intrinsic::arm_neon_vst2lane:
16022 case Intrinsic::arm_neon_vst3lane:
16028 case Intrinsic::arm_neon_vst4lane:
16034 case Intrinsic::arm_neon_vst1x2:
16038 hasAlignment =
false;
16040 case Intrinsic::arm_neon_vst1x3:
16044 hasAlignment =
false;
16046 case Intrinsic::arm_neon_vst1x4:
16050 hasAlignment =
false;
16055 switch (
N->getOpcode()) {
16091 VecTy =
N->getValueType(0);
16092 }
else if (
Target.isIntrinsic) {
16093 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16096 "Node has to be a load, a store, or an intrinsic!");
16097 VecTy =
N->getOperand(1).getValueType();
16105 if (isLaneOp || isVLDDUPOp)
16108 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16114 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16123 EVT AlignedVecTy = VecTy;
16143 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16144 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16155 Alignment =
Align(1);
16161 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16163 for (n = 0; n < NumResultVecs; ++n)
16164 Tys[n] = AlignedVecTy;
16165 Tys[n++] = MVT::i32;
16166 Tys[n] = MVT::Other;
16171 Ops.push_back(
N->getOperand(0));
16172 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16177 Ops.push_back(StN->getValue());
16181 unsigned LastOperand =
16182 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16183 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16184 Ops.push_back(
N->getOperand(i));
16192 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16203 for (
unsigned i = 0; i < NumResultVecs; ++i)
16208 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16209 SDValue &LdVal = NewResults[0];
16245 switch (
N->getOpcode()) {
16249 *Ptr =
N->getOperand(0);
16250 *CInc =
N->getOperand(1);
16257 *Ptr =
N->getOperand(1);
16258 *CInc =
N->getOperand(2);
16285 SDValue Addr =
N->getOperand(AddrOpIdx);
16296 unsigned ConstInc =
16301 if (BaseUpdates.
size() >= MaxBaseUpdates)
16322 unsigned UserOffset =
16325 if (!UserOffset || UserOffset <=
Offset)
16328 unsigned NewConstInc = UserOffset -
Offset;
16331 if (BaseUpdates.
size() >= MaxBaseUpdates)
16339 unsigned NumValidUpd = BaseUpdates.
size();
16340 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16351 return LHS.ConstInc <
RHS.ConstInc;
16380 unsigned IntNo =
N->getConstantOperandVal(1);
16381 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16383 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16406 bool isLoadOp =
true;
16407 unsigned NewOpc = 0;
16408 unsigned NumVecs = 0;
16412 case Intrinsic::arm_mve_vld2q:
16416 case Intrinsic::arm_mve_vld4q:
16420 case Intrinsic::arm_mve_vst2q:
16421 NewOpc = ARMISD::VST2_UPD;
16425 case Intrinsic::arm_mve_vst4q:
16426 NewOpc = ARMISD::VST4_UPD;
16435 VecTy =
N->getValueType(0);
16437 VecTy =
N->getOperand(3).getValueType();
16451 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16453 for (n = 0; n < NumResultVecs; ++n)
16455 Tys[n++] = MVT::i32;
16456 Tys[n] = MVT::Other;
16461 Ops.push_back(
N->getOperand(0));
16462 Ops.push_back(
N->getOperand(2));
16463 Ops.push_back(Inc);
16465 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16466 Ops.push_back(
N->getOperand(i));
16473 for (
unsigned i = 0; i < NumResultVecs; ++i)
16492 EVT VT =
N->getValueType(0);
16498 SDNode *VLD =
N->getOperand(0).getNode();
16501 unsigned NumVecs = 0;
16502 unsigned NewOpc = 0;
16504 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16507 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16510 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16522 if (
Use.getResNo() == NumVecs)
16525 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16526 VLDLaneNo !=
User->getConstantOperandVal(1))
16533 for (n = 0; n < NumVecs; ++n)
16535 Tys[n] = MVT::Other;
16545 unsigned ResNo =
Use.getResNo();
16547 if (ResNo == NumVecs)
16554 std::vector<SDValue> VLDDupResults;
16555 for (
unsigned n = 0; n < NumVecs; ++n)
16569 EVT VT =
N->getValueType(0);
16572 if (Subtarget->hasMVEIntegerOps()) {
16576 ExtractVT = MVT::i32;
16578 N->getOperand(0),
N->getOperand(1));
16590 Op =
Op.getOperand(0);
16591 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16595 unsigned EltSize =
Op.getScalarValueSizeInBits();
16597 unsigned Imm =
Op.getConstantOperandVal(0);
16613 if (Subtarget->hasMVEIntegerOps()) {
16616 if (
Op.getValueType() == MVT::f32)
16617 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16619 else if (
Op.getValueType() == MVT::f16)
16620 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16621 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16624 if (!Subtarget->hasNEON())
16631 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16632 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16633 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16638 LD->getMemoryVT(), LD->getMemOperand());
16649 EVT VT =
N->getValueType(0);
16671 assert(StVT != VT &&
"Cannot truncate to the same type");
16681 if (0 != (NumElems * FromEltSz) % ToEltSz)
16684 unsigned SizeRatio = FromEltSz / ToEltSz;
16689 NumElems * SizeRatio);
16695 for (
unsigned i = 0; i < NumElems; ++i)
16709 MVT StoreType = MVT::i8;
16711 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16731 for (
unsigned I = 0;
I <
E;
I++) {
16762 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16765 unsigned NumElements = 4;
16782 unsigned Off0 = Rev ? NumElts : 0;
16783 unsigned Off1 = Rev ? 0 : NumElts;
16785 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16786 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16788 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16796 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16816 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16827 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16831 NewToVT, Alignment, MMOFlags, AAInfo);
16864 unsigned NewOffset =
16872 NewToVT, Alignment, MMOFlags, AAInfo);
16894 {Extract.getOperand(0), Extract.getOperand(1)});
16925 if (Subtarget->hasNEON())
16929 if (Subtarget->hasMVEFloatOps())
16933 if (Subtarget->hasMVEIntegerOps()) {
17007 if (!Subtarget->hasNEON())
17011 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
17019 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
17021 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
17022 uint32_t IntBits = IntTy.getSizeInBits();
17023 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17024 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17035 if (
C == -1 ||
C == 0 ||
C > 32)
17040 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
17041 Intrinsic::arm_neon_vcvtfp2fxu;
17044 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
17047 if (IntBits < FloatBits)
17055 if (!Subtarget->hasMVEFloatOps())
17063 EVT VT =
N->getValueType(0);
17068 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
17070 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
17072 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
17073 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
17075 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17088 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17099 EVT VT =
N->getValueType(0);
17102 if (!
N->getFlags().hasAllowReassociation())
17109 unsigned Opc =
A.getConstantOperandVal(0);
17110 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17115 A.getOperand(3),
A.getOperand(4));
17147 if (!Subtarget->hasNEON())
17151 unsigned OpOpcode =
Op.getNode()->getOpcode();
17152 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17156 SDValue ConstVec =
N->getOperand(1);
17160 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17162 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17163 uint32_t IntBits = IntTy.getSizeInBits();
17164 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17165 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17185 int32_t
C = IntVal.exactLogBase2();
17186 if (
C == -1 ||
C == 0 ||
C > 32)
17192 if (IntBits < FloatBits)
17194 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17196 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17197 : Intrinsic::arm_neon_vcvtfxu2fp;
17205 if (!ST->hasMVEIntegerOps())
17209 EVT ResVT =
N->getValueType(0);
17237 EVT AVT =
A.getValueType();
17243 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17244 EVT AVT =
A.getValueType();
17254 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17255 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17258 if (ExtTypeMatches(
A, ExtTypes))
17259 return ExtendIfNeeded(
A, ExtendCode);
17262 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17272 if (ExtTypeMatches(
A, ExtTypes))
17273 return ExtendIfNeeded(
A, ExtendCode);
17276 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17286 if (ResVT != RetTy)
17289 if (
Mul->getOpcode() == ExtendCode &&
17290 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17292 Mul =
Mul->getOperand(0);
17301 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17302 A = ExtendIfNeeded(
A, ExtendCode);
17303 B = ExtendIfNeeded(
B, ExtendCode);
17308 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17321 if (
Mul->getOpcode() == ExtendCode &&
17322 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17324 Mul =
Mul->getOperand(0);
17333 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17334 A = ExtendIfNeeded(
A, ExtendCode);
17335 B = ExtendIfNeeded(
B, ExtendCode);
17346 EVT VT =
Ops[0].getValueType();
17347 if (VT == MVT::v16i8) {
17348 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17349 "Unexpected illegal long reduction opcode");
17350 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17362 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17375 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17377 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17378 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17380 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17381 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17383 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17386 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17389 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17393 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17396 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17399 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17402 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17405 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17408 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17411 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17413 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17415 return Create64bitNode(ARMISD::VADDLVs, {
A});
17417 return Create64bitNode(ARMISD::VADDLVu, {
A});
17420 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17423 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17426 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17428 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17430 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17432 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17435 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17438 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17445 Op =
Op->getOperand(1);
17447 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17449 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17466 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17468 if (!Shuf || !Shuf->getOperand(1).isUndef())
17473 APInt SetElts(Mask.size(), 0);
17474 for (
int E : Mask) {
17482 if (
N->getNumOperands() != VecOp + 1) {
17484 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17490 if (
Op.getValueType().isVector())
17491 Ops.push_back(
Op.getOperand(0));
17502 unsigned IsTop =
N->getConstantOperandVal(2);
17509 if (Op0->
isUndef() && !IsTop)
17514 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17515 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17523 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17525 APInt Op0DemandedElts =
17526 IsTop ? Op1DemandedElts
17541 unsigned IsTop =
N->getConstantOperandVal(2);
17543 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17544 APInt Op0DemandedElts =
17556 EVT VT =
N->getValueType(0);
17563 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17564 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17568 LHS.getOperand(0),
RHS.getOperand(0));
17583 int ShiftAmt =
C->getSExtValue();
17584 if (ShiftAmt == 0) {
17590 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17591 unsigned NewOpcode =
17592 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17607 unsigned IntNo =
N->getConstantOperandVal(0);
17618 case Intrinsic::arm_neon_vshifts:
17619 case Intrinsic::arm_neon_vshiftu:
17620 case Intrinsic::arm_neon_vrshifts:
17621 case Intrinsic::arm_neon_vrshiftu:
17622 case Intrinsic::arm_neon_vrshiftn:
17623 case Intrinsic::arm_neon_vqshifts:
17624 case Intrinsic::arm_neon_vqshiftu:
17625 case Intrinsic::arm_neon_vqshiftsu:
17626 case Intrinsic::arm_neon_vqshiftns:
17627 case Intrinsic::arm_neon_vqshiftnu:
17628 case Intrinsic::arm_neon_vqshiftnsu:
17629 case Intrinsic::arm_neon_vqrshiftns:
17630 case Intrinsic::arm_neon_vqrshiftnu:
17631 case Intrinsic::arm_neon_vqrshiftnsu: {
17632 EVT VT =
N->getOperand(1).getValueType();
17634 unsigned VShiftOpc = 0;
17637 case Intrinsic::arm_neon_vshifts:
17638 case Intrinsic::arm_neon_vshiftu:
17640 VShiftOpc = ARMISD::VSHLIMM;
17643 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17644 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17645 : ARMISD::VSHRuIMM);
17650 case Intrinsic::arm_neon_vrshifts:
17651 case Intrinsic::arm_neon_vrshiftu:
17656 case Intrinsic::arm_neon_vqshifts:
17657 case Intrinsic::arm_neon_vqshiftu:
17662 case Intrinsic::arm_neon_vqshiftsu:
17667 case Intrinsic::arm_neon_vrshiftn:
17668 case Intrinsic::arm_neon_vqshiftns:
17669 case Intrinsic::arm_neon_vqshiftnu:
17670 case Intrinsic::arm_neon_vqshiftnsu:
17671 case Intrinsic::arm_neon_vqrshiftns:
17672 case Intrinsic::arm_neon_vqrshiftnu:
17673 case Intrinsic::arm_neon_vqrshiftnsu:
17685 case Intrinsic::arm_neon_vshifts:
17686 case Intrinsic::arm_neon_vshiftu:
17689 case Intrinsic::arm_neon_vrshifts:
17690 VShiftOpc = ARMISD::VRSHRsIMM;
17692 case Intrinsic::arm_neon_vrshiftu:
17693 VShiftOpc = ARMISD::VRSHRuIMM;
17695 case Intrinsic::arm_neon_vrshiftn:
17696 VShiftOpc = ARMISD::VRSHRNIMM;
17698 case Intrinsic::arm_neon_vqshifts:
17699 VShiftOpc = ARMISD::VQSHLsIMM;
17701 case Intrinsic::arm_neon_vqshiftu:
17702 VShiftOpc = ARMISD::VQSHLuIMM;
17704 case Intrinsic::arm_neon_vqshiftsu:
17705 VShiftOpc = ARMISD::VQSHLsuIMM;
17707 case Intrinsic::arm_neon_vqshiftns:
17708 VShiftOpc = ARMISD::VQSHRNsIMM;
17710 case Intrinsic::arm_neon_vqshiftnu:
17711 VShiftOpc = ARMISD::VQSHRNuIMM;
17713 case Intrinsic::arm_neon_vqshiftnsu:
17714 VShiftOpc = ARMISD::VQSHRNsuIMM;
17716 case Intrinsic::arm_neon_vqrshiftns:
17717 VShiftOpc = ARMISD::VQRSHRNsIMM;
17719 case Intrinsic::arm_neon_vqrshiftnu:
17720 VShiftOpc = ARMISD::VQRSHRNuIMM;
17722 case Intrinsic::arm_neon_vqrshiftnsu:
17723 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17728 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17729 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17732 case Intrinsic::arm_neon_vshiftins: {
17733 EVT VT =
N->getOperand(1).getValueType();
17735 unsigned VShiftOpc = 0;
17738 VShiftOpc = ARMISD::VSLIIMM;
17739 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17740 VShiftOpc = ARMISD::VSRIIMM;
17746 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17747 N->getOperand(1),
N->getOperand(2),
17751 case Intrinsic::arm_neon_vqrshifts:
17752 case Intrinsic::arm_neon_vqrshiftu:
17756 case Intrinsic::arm_neon_vbsl: {
17758 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17759 N->getOperand(2),
N->getOperand(3));
17761 case Intrinsic::arm_mve_vqdmlah:
17762 case Intrinsic::arm_mve_vqdmlash:
17763 case Intrinsic::arm_mve_vqrdmlah:
17764 case Intrinsic::arm_mve_vqrdmlash:
17765 case Intrinsic::arm_mve_vmla_n_predicated:
17766 case Intrinsic::arm_mve_vmlas_n_predicated:
17767 case Intrinsic::arm_mve_vqdmlah_predicated:
17768 case Intrinsic::arm_mve_vqdmlash_predicated:
17769 case Intrinsic::arm_mve_vqrdmlah_predicated:
17770 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17775 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17782 case Intrinsic::arm_mve_minv:
17783 case Intrinsic::arm_mve_maxv:
17784 case Intrinsic::arm_mve_minav:
17785 case Intrinsic::arm_mve_maxav:
17786 case Intrinsic::arm_mve_minv_predicated:
17787 case Intrinsic::arm_mve_maxv_predicated:
17788 case Intrinsic::arm_mve_minav_predicated:
17789 case Intrinsic::arm_mve_maxav_predicated: {
17792 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17799 case Intrinsic::arm_mve_addv: {
17802 bool Unsigned =
N->getConstantOperandVal(2);
17803 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17807 case Intrinsic::arm_mve_addlv:
17808 case Intrinsic::arm_mve_addlv_predicated: {
17811 bool Unsigned =
N->getConstantOperandVal(2);
17812 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17813 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17814 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17817 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17819 Ops.push_back(
N->getOperand(i));
17832 EVT VT =
Y.getValueType();
17835 if (Subtarget->hasMVEIntegerOps())
17837 if (Subtarget->hasNEON())
17851 EVT VT =
N->getValueType(0);
17853 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17854 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17855 N->getOperand(0)->hasOneUse()) {
17872 if (AndMask == 255 || AndMask == 65535)
17876 if (MaskedBits > ShiftAmt) {
17891 if (ST->hasMVEIntegerOps())
17896 switch (
N->getOpcode()) {
17902 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17909 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17910 unsigned VShiftOpc =
17911 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17913 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17929 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17932 EVT FromVT = LD->getValueType(0);
17933 EVT ToVT =
N->getValueType(0);
17940 unsigned NumElements = 0;
17941 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17943 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17945 if (NumElements == 0 ||
17955 SDValue BasePtr = LD->getBasePtr();
17956 Align Alignment = LD->getBaseAlign();
17977 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17978 Alignment, MMOFlags, AAInfo);
17984 if (FromEltVT == MVT::f16) {
17987 for (
unsigned i = 0; i < Loads.
size(); i++) {
17989 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
18008 EVT VT =
N->getValueType(0);
18015 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
18022 if (VT == MVT::i32 &&
18023 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
18028 switch (
N->getOpcode()) {
18031 Opc = ARMISD::VGETLANEs;
18035 Opc = ARMISD::VGETLANEu;
18042 if (ST->hasMVEIntegerOps())
18060 Ops.push_back(Ext);
18070 if (ST->hasMVEFloatOps())
18081 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
18085 EVT VT =
Op.getValueType();
18088 if (VT != MVT::i32 ||
18104 APInt MaxC = Max.getConstantOperandAPInt(1);
18105 if (MaxC.
sgt(MinC))
18112 if ((MinC + 1).isPowerOf2()) {
18134 APInt Width = MinC - MaxC + 1;
18137 unsigned SatBit = Width.
logBase2() - 1;
18155 EVT VT =
N->getValueType(0);
18158 if (VT == MVT::i32)
18161 if (!ST->hasMVEIntegerOps())
18167 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18170 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18178 if (VT == MVT::v4i32)
18179 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18181 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18188 MaxC != ~SaturateC)
18193 if (IsSignedSaturate(
N, N0.
getNode())) {
18196 if (VT == MVT::v4i32) {
18197 HalfVT = MVT::v8i16;
18198 ExtVT = MVT::v4i16;
18200 HalfVT = MVT::v16i8;
18215 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18221 if (VT == MVT::v4i32)
18222 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18224 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18233 if (IsUnsignedSaturate(
N)) {
18237 if (VT == MVT::v4i32) {
18238 HalfVT = MVT::v8i16;
18239 ExtConst = 0x0000FFFF;
18241 HalfVT = MVT::v16i8;
18263 const APInt *CV = &
C->getAPIntValue();
18320 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18327 if ((OrCI & Known.
Zero) != OrCI)
18333 EVT VT =
X.getValueType();
18334 unsigned BitInX = AndC->
logBase2();
18342 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18343 BitInY < NumActiveBits; ++BitInY) {
18344 if (OrCI[BitInY] == 0)
18347 Mask.setBit(BitInY);
18348 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18364 switch (
N->getOpcode()) {
18379 if (Const->isZero())
18381 else if (Const->isOne())
18389 unsigned IntOp =
N.getConstantOperandVal(1);
18390 if (IntOp != Intrinsic::test_start_loop_iterations &&
18391 IntOp != Intrinsic::loop_decrement_reg)
18417 bool Negate =
false;
18423 Cond =
N->getOperand(1);
18424 Dest =
N->getOperand(2);
18428 Cond =
N->getOperand(2);
18429 Dest =
N->getOperand(4);
18431 if (!Const->isOne() && !Const->isZero())
18433 Imm = Const->getZExtValue();
18461 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18462 "unsupported condition");
18467 unsigned IntOp =
Int->getConstantOperandVal(1);
18468 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18469 "expected single br user");
18470 SDNode *Br = *
N->user_begin();
18480 if (IntOp == Intrinsic::test_start_loop_iterations) {
18482 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18484 if (IsTrueIfZero(CC, Imm)) {
18486 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18490 UpdateUncondBr(Br, Dest, DAG);
18492 SDValue Ops[] = {Chain, Setup, OtherTarget};
18493 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18505 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18509 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18513 if (
Target == OtherTarget)
18514 UpdateUncondBr(Br, Dest, DAG);
18520 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18529 if (Cmp.getOpcode() != ARMISD::CMPZ)
18534 SDValue LHS = Cmp.getOperand(0);
18535 SDValue RHS = Cmp.getOperand(1);
18544 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18545 LHS->getOperand(0)->hasOneUse() &&
18549 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18561 EVT VT =
N->getValueType(0);
18562 SDValue FalseVal =
N->getOperand(0);
18563 SDValue TrueVal =
N->getOperand(1);
18571 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18578 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18581 if (Cmp.getOpcode() != ARMISD::CMPZ)
18585 SDValue LHS = Cmp.getOperand(0);
18586 SDValue RHS = Cmp.getOperand(1);
18590 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18614 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18615 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18616 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18619 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18624 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18627 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18628 LHS->getOperand(2), LHS->getOperand(3));
18638 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18642 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18644 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18653 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18686 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18698 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18718 const APInt *TrueConst;
18719 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18720 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18721 FalseVal.getOperand(1) == RHS) ||
18725 unsigned ShiftAmount = TrueConst->
logBase2();
18740 if (Known.
Zero == 0xfffffffe)
18743 else if (Known.
Zero == 0xffffff00)
18746 else if (Known.
Zero == 0xffff0000)
18759 EVT DstVT =
N->getValueType(0);
18762 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18763 EVT SrcVT = Src.getValueType();
18765 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18770 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18771 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18772 Src.getValueType().getScalarSizeInBits())
18773 Src = Src.getOperand(0);
18777 EVT SrcVT = Src.getValueType();
18778 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18779 Src.getOpcode() == ARMISD::VMVNIMM ||
18780 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18783 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18797 EVT VT =
N->getValueType(0);
18805 if (
N->getNumOperands() == 2 &&
18809 N->getOperand(0).getOperand(1),
18810 N->getOperand(1).getOperand(0),
18811 N->getOperand(1).getOperand(1));
18814 if (
N->getNumOperands() == 2 &&
18820 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18821 S0->getOperand(1) ==
S1->getOperand(1)) {
18824 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18828 ARMISD::VMOVN,
DL, VT,
18829 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18830 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18834 ARMISD::VMOVN,
DL, VT,
18835 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18836 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18844 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18845 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18846 (Op.getOpcode() == ISD::BITCAST &&
18847 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18850 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18852 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18870 int NumIns =
N->getNumOperands();
18871 assert((NumIns == 2 || NumIns == 4) &&
18872 "Expected 2 or 4 inputs to an MVETrunc");
18874 if (
N->getNumOperands() == 4)
18878 for (
int I = 0;
I < NumIns;
I++) {
18880 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18885 Ptr, MPI, StoreVT,
Align(4));
18900 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18903 EVT FromVT = LD->getMemoryVT();
18904 EVT ToVT =
N->getValueType(0);
18911 unsigned NumElements = 0;
18912 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18914 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18916 assert(NumElements != 0);
18922 LD->getExtensionType() != NewExtType)
18929 SDValue BasePtr = LD->getBasePtr();
18930 Align Alignment = LD->getBaseAlign();
18949 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18950 Alignment, MMOFlags, AAInfo);
18966 EVT VT =
N->getValueType(0);
18968 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18969 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18971 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18973 auto Extend = [&](
SDValue V) {
18982 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
18983 SDValue Ext = Extend(
N->getOperand(0));
18991 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18992 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
18996 auto CheckInregMask = [&](
int Start,
int Offset) {
18998 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
19004 if (CheckInregMask(0, 0))
19006 else if (CheckInregMask(0, 1))
19007 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19008 else if (CheckInregMask(0, Mask.size()))
19010 else if (CheckInregMask(0, Mask.size() + 1))
19011 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19016 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19020 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19027 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
19038 int NumOuts =
N->getNumValues();
19039 assert((NumOuts == 2 || NumOuts == 4) &&
19040 "Expected 2 or 4 outputs to an MVEEXT");
19041 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19043 if (
N->getNumOperands() == 4)
19049 StackPtr, MPI,
Align(4));
19052 for (
int I = 0;
I < NumOuts;
I++) {
19054 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
19055 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
19060 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
19069 switch (
N->getOpcode()) {
19129 case ARMISD::BRCOND:
19133 case ARMISD::CSINC:
19134 case ARMISD::CSINV:
19135 case ARMISD::CSNEG:
19148 case ARMISD::PREDICATE_CAST:
19150 case ARMISD::VECTOR_REG_CAST:
19161 case ARMISD::VADDVs:
19162 case ARMISD::VADDVu:
19163 case ARMISD::VADDLVs:
19164 case ARMISD::VADDLVu:
19165 case ARMISD::VADDLVAs:
19166 case ARMISD::VADDLVAu:
19167 case ARMISD::VMLAVs:
19168 case ARMISD::VMLAVu:
19169 case ARMISD::VMLALVs:
19170 case ARMISD::VMLALVu:
19171 case ARMISD::VMLALVAs:
19172 case ARMISD::VMLALVAu:
19174 case ARMISD::VMOVN:
19176 case ARMISD::VQMOVNs:
19177 case ARMISD::VQMOVNu:
19179 case ARMISD::VQDMULH:
19185 case ARMISD::SMULWB: {
19186 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19192 case ARMISD::SMULWT: {
19193 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19199 case ARMISD::SMLALBB:
19200 case ARMISD::QADD16b:
19201 case ARMISD::QSUB16b:
19202 case ARMISD::UQADD16b:
19203 case ARMISD::UQSUB16b: {
19204 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19211 case ARMISD::SMLALBT: {
19212 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19214 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19221 case ARMISD::SMLALTB: {
19222 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19224 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19231 case ARMISD::SMLALTT: {
19232 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19239 case ARMISD::QADD8b:
19240 case ARMISD::QSUB8b:
19241 case ARMISD::UQADD8b:
19242 case ARMISD::UQSUB8b: {
19243 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19251 if (
N->getOperand(1) ==
N->getOperand(2))
19252 return N->getOperand(1);
19256 switch (
N->getConstantOperandVal(1)) {
19257 case Intrinsic::arm_neon_vld1:
19258 case Intrinsic::arm_neon_vld1x2:
19259 case Intrinsic::arm_neon_vld1x3:
19260 case Intrinsic::arm_neon_vld1x4:
19261 case Intrinsic::arm_neon_vld2:
19262 case Intrinsic::arm_neon_vld3:
19263 case Intrinsic::arm_neon_vld4:
19264 case Intrinsic::arm_neon_vld2lane:
19265 case Intrinsic::arm_neon_vld3lane:
19266 case Intrinsic::arm_neon_vld4lane:
19267 case Intrinsic::arm_neon_vld2dup:
19268 case Intrinsic::arm_neon_vld3dup:
19269 case Intrinsic::arm_neon_vld4dup:
19270 case Intrinsic::arm_neon_vst1:
19271 case Intrinsic::arm_neon_vst1x2:
19272 case Intrinsic::arm_neon_vst1x3:
19273 case Intrinsic::arm_neon_vst1x4:
19274 case Intrinsic::arm_neon_vst2:
19275 case Intrinsic::arm_neon_vst3:
19276 case Intrinsic::arm_neon_vst4:
19277 case Intrinsic::arm_neon_vst2lane:
19278 case Intrinsic::arm_neon_vst3lane:
19279 case Intrinsic::arm_neon_vst4lane:
19281 case Intrinsic::arm_mve_vld2q:
19282 case Intrinsic::arm_mve_vld4q:
19283 case Intrinsic::arm_mve_vst2q:
19284 case Intrinsic::arm_mve_vst4q:
19301 unsigned *
Fast)
const {
19307 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19310 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19312 if (AllowsUnaligned) {
19314 *
Fast = Subtarget->hasV7Ops();
19319 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19323 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19330 if (!Subtarget->hasMVEIntegerOps())
19334 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19335 Ty == MVT::v2i1)) {
19343 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19359 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19360 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19361 Ty == MVT::v2f64) {
19372 const AttributeList &FuncAttributes)
const {
19374 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19375 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19377 if (
Op.size() >= 16 &&
19383 }
else if (
Op.size() >= 8 &&
19400 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19402 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19404 return (SrcBits == 64 && DestBits == 32);
19413 return (SrcBits == 64 && DestBits == 32);
19449 return Subtarget->hasFullFP16();
19456 if (!Subtarget->hasMVEIntegerOps())
19475 if (Ld->isExpandingLoad())
19479 if (Subtarget->hasMVEIntegerOps())
19492 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19524bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19526 if (Subtarget->useSoftFloat())
19535 return Subtarget->hasMVEFloatOps();
19553 unsigned Scale = 1;
19570 if ((V & (Scale - 1)) != 0)
19579 if (VT.
isVector() && Subtarget->hasNEON())
19582 !Subtarget->hasMVEFloatOps())
19585 bool IsNeg =
false;
19591 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19594 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19610 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19616 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19646 default:
return false;
19665 int Scale = AM.
Scale;
19670 default:
return false;
19678 Scale = Scale & ~1;
19679 return Scale == 2 || Scale == 4 || Scale == 8;
19696 if (Scale & 1)
return false;
19703 const int Scale = AM.
Scale;
19713 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19729 switch (AM.
Scale) {
19740 if (Subtarget->isThumb1Only())
19743 if (Subtarget->isThumb2())
19746 int Scale = AM.
Scale;
19748 default:
return false;
19752 if (Scale < 0) Scale = -Scale;
19760 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19773 if (Scale & 1)
return false;
19786 if (!Subtarget->isThumb())
19789 if (Subtarget->isThumb2())
19793 return Imm >= 0 && Imm <= 255;
19803 if (!Subtarget->isThumb())
19805 if (Subtarget->isThumb2())
19808 return AbsImm <= 255;
19843 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19847 int RHSC = (int)
RHS->getZExtValue();
19848 if (RHSC < 0 && RHSC > -256) {
19858 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19861 int RHSC = (int)
RHS->getZExtValue();
19862 if (RHSC < 0 && RHSC > -0x1000) {
19904 int RHSC = (int)
RHS->getZExtValue();
19905 if (RHSC < 0 && RHSC > -0x100) {
19910 }
else if (RHSC > 0 && RHSC < 0x100) {
19921 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19932 bool CanChangeType = isLE && !IsMasked;
19935 int RHSC = (int)
RHS->getZExtValue();
19937 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19938 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19943 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19954 if (VT == MVT::v4i16) {
19955 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19957 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19958 if (IsInRange(RHSC, 0x80, 1))
19960 }
else if (Alignment >= 4 &&
19961 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19962 IsInRange(RHSC, 0x80, 4))
19964 else if (Alignment >= 2 &&
19965 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19966 IsInRange(RHSC, 0x80, 2))
19968 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19981 if (Subtarget->isThumb1Only())
19988 bool isSEXTLoad =
false;
19989 bool IsMasked =
false;
19991 Ptr = LD->getBasePtr();
19992 VT = LD->getMemoryVT();
19993 Alignment = LD->getAlign();
19994 AS = LD->getAddressSpace();
19997 Ptr = ST->getBasePtr();
19998 VT = ST->getMemoryVT();
19999 Alignment = ST->getAlign();
20000 AS = ST->getAddressSpace();
20002 Ptr = LD->getBasePtr();
20003 VT = LD->getMemoryVT();
20004 Alignment = LD->getAlign();
20005 AS = LD->getAddressSpace();
20009 Ptr = ST->getBasePtr();
20010 VT = ST->getMemoryVT();
20011 Alignment = ST->getAlign();
20012 AS = ST->getAddressSpace();
20027 bool isLegal =
false;
20029 isLegal = Subtarget->hasMVEIntegerOps() &&
20031 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
20032 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
20034 if (Subtarget->isThumb2())
20059 bool isSEXTLoad =
false, isNonExt;
20060 bool IsMasked =
false;
20062 VT = LD->getMemoryVT();
20063 Ptr = LD->getBasePtr();
20064 Alignment = LD->getAlign();
20068 VT = ST->getMemoryVT();
20069 Ptr = ST->getBasePtr();
20070 Alignment = ST->getAlign();
20071 isNonExt = !ST->isTruncatingStore();
20073 VT = LD->getMemoryVT();
20074 Ptr = LD->getBasePtr();
20075 Alignment = LD->getAlign();
20080 VT = ST->getMemoryVT();
20081 Ptr = ST->getBasePtr();
20082 Alignment = ST->getAlign();
20083 isNonExt = !ST->isTruncatingStore();
20088 if (Subtarget->isThumb1Only()) {
20091 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
20092 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
20095 if (!RHS || RHS->getZExtValue() != 4)
20097 if (Alignment <
Align(4))
20101 Base =
Op->getOperand(0);
20107 bool isLegal =
false;
20109 isLegal = Subtarget->hasMVEIntegerOps() &&
20114 if (Subtarget->isThumb2())
20128 !Subtarget->isThumb2())
20142 const APInt &DemandedElts,
20144 unsigned Depth)
const {
20147 switch (
Op.getOpcode()) {
20154 if (
Op.getResNo() == 0) {
20165 case ARMISD::CMOV: {
20180 case Intrinsic::arm_ldaex:
20181 case Intrinsic::arm_ldrex: {
20189 case ARMISD::BFI: {
20196 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20197 Known.
Zero &= Mask;
20201 case ARMISD::VGETLANEs:
20202 case ARMISD::VGETLANEu: {
20203 const SDValue &SrcSV =
Op.getOperand(0);
20209 "VGETLANE index out of bounds");
20214 EVT VT =
Op.getValueType();
20220 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20221 Known = Known.
sext(DstSz);
20223 Known = Known.
zext(DstSz);
20228 case ARMISD::VMOVrh: {
20231 Known = KnownOp.
zext(32);
20234 case ARMISD::CSINC:
20235 case ARMISD::CSINV:
20236 case ARMISD::CSNEG: {
20244 if (
Op.getOpcode() == ARMISD::CSINC)
20247 else if (
Op.getOpcode() == ARMISD::CSINV)
20249 else if (
Op.getOpcode() == ARMISD::CSNEG)
20256 case ARMISD::VORRIMM:
20257 case ARMISD::VBICIMM: {
20258 unsigned Encoded =
Op.getConstantOperandVal(1);
20259 unsigned DecEltBits = 0;
20262 unsigned EltBits =
Op.getScalarValueSizeInBits();
20263 if (EltBits != DecEltBits) {
20272 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20273 APInt Imm(DecEltBits, DecodedVal);
20275 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20276 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20284 if (!Subtarget->isThumb())
20301 if (Imm == 0 || Imm == ~0U)
20304 unsigned Opc =
Op.getOpcode();
20306 EVT VT =
Op.getValueType();
20308 unsigned ShrunkImm = Imm & Demanded;
20309 unsigned ExpandedImm = Imm | ~Demanded;
20311 auto IsLegalImm = [ShrunkImm, ExpandedImm](
unsigned CandidateImm) ->
bool {
20312 return (ShrunkImm & CandidateImm) == ShrunkImm &&
20313 (~ExpandedImm & CandidateImm) == 0;
20315 auto UseImm = [Imm,
Opc,
Op, VT, &TLO](
unsigned NewImm) ->
bool {
20327 if (ShrunkImm == 0) {
20328 ++NumOptimizedImms;
20329 return UseImm(ShrunkImm);
20335 if (ExpandedImm == ~0U) {
20336 ++NumOptimizedImms;
20337 return UseImm(ExpandedImm);
20345 if (IsLegalImm(0xFF)) {
20346 ++NumOptimizedImms;
20347 return UseImm(0xFF);
20350 if (IsLegalImm(0xFFFF)) {
20351 ++NumOptimizedImms;
20352 return UseImm(0xFFFF);
20366 ++NumOptimizedImms;
20367 return UseImm(ShrunkImm);
20375 if ((~ExpandedImm) < 256) {
20376 ++NumOptimizedImms;
20377 return UseImm(ExpandedImm);
20383 !Subtarget->hasV6Ops()) {
20384 ++NumOptimizedImms;
20385 return UseImm(ExpandedImm);
20404 EVT VT =
Op.getValueType();
20419 switch (
Op.getOpcode()) {
20430 unsigned Imm =
C->getZExtValue();
20437 unsigned Depth)
const {
20438 unsigned Opc =
Op.getOpcode();
20442 case ARMISD::LSRL: {
20446 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20448 unsigned ShAmt =
Op->getConstantOperandVal(2);
20458 case ARMISD::VBICIMM: {
20460 unsigned ModImm =
Op.getConstantOperandVal(1);
20461 unsigned EltBits = 0;
20463 if ((OriginalDemandedBits & Mask) == 0)
20469 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20484 if (!Subtarget->hasVFP2Base())
20488 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20500 unsigned S = Constraint.
size();
20502 switch (Constraint[0]) {
20514 }
else if (S == 2) {
20515 switch (Constraint[0]) {
20532 Value *CallOperandVal =
info.CallOperandVal;
20535 if (!CallOperandVal)
20539 switch (*constraint) {
20545 if (Subtarget->isThumb())
20560 if (PR == 0 || VT == MVT::Other)
20562 if (ARM::SPRRegClass.
contains(PR))
20563 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20564 if (ARM::DPRRegClass.
contains(PR))
20569using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20573 switch (Constraint.
size()) {
20576 switch (Constraint[0]) {
20578 if (Subtarget->isThumb())
20579 return RCPair(0U, &ARM::tGPRRegClass);
20580 return RCPair(0U, &ARM::GPRRegClass);
20582 if (Subtarget->isThumb())
20583 return RCPair(0U, &ARM::hGPRRegClass);
20586 if (Subtarget->isThumb1Only())
20587 return RCPair(0U, &ARM::tGPRRegClass);
20588 return RCPair(0U, &ARM::GPRRegClass);
20590 if (VT == MVT::Other)
20592 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20593 return RCPair(0U, &ARM::SPRRegClass);
20595 return RCPair(0U, &ARM::DPRRegClass);
20597 return RCPair(0U, &ARM::QPRRegClass);
20600 if (VT == MVT::Other)
20602 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20603 return RCPair(0U, &ARM::SPR_8RegClass);
20605 return RCPair(0U, &ARM::DPR_8RegClass);
20607 return RCPair(0U, &ARM::QPR_8RegClass);
20610 if (VT == MVT::Other)
20612 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20613 return RCPair(0U, &ARM::SPRRegClass);
20615 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20617 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20623 if (Constraint[0] ==
'T') {
20624 switch (Constraint[1]) {
20628 return RCPair(0U, &ARM::tGPREvenRegClass);
20630 return RCPair(0U, &ARM::tGPROddRegClass);
20639 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20640 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20643 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20644 return std::make_pair(
unsigned(ARM::LR),
getRegClassFor(MVT::i32));
20648 return {0,
nullptr};
20656 std::vector<SDValue> &
Ops,
20661 if (Constraint.
size() != 1)
20664 char ConstraintLetter = Constraint[0];
20665 switch (ConstraintLetter) {
20668 case 'I':
case 'J':
case 'K':
case 'L':
20669 case 'M':
case 'N':
case 'O':
20674 int64_t CVal64 =
C->getSExtValue();
20675 int CVal = (int) CVal64;
20678 if (CVal != CVal64)
20681 switch (ConstraintLetter) {
20685 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20686 if (CVal >= 0 && CVal <= 65535)
20690 if (Subtarget->isThumb1Only()) {
20693 if (CVal >= 0 && CVal <= 255)
20695 }
else if (Subtarget->isThumb2()) {
20709 if (Subtarget->isThumb1Only()) {
20714 if (CVal >= -255 && CVal <= -1)
20720 if (CVal >= -4095 && CVal <= 4095)
20726 if (Subtarget->isThumb1Only()) {
20733 }
else if (Subtarget->isThumb2()) {
20753 if (Subtarget->isThumb1Only()) {
20756 if (CVal >= -7 && CVal < 7)
20758 }
else if (Subtarget->isThumb2()) {
20778 if (Subtarget->isThumb1Only()) {
20781 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20787 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20793 if (Subtarget->isThumb1Only()) {
20795 if (CVal >= 0 && CVal <= 31)
20801 if (Subtarget->isThumb1Only()) {
20804 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20813 if (Result.getNode()) {
20814 Ops.push_back(Result);
20824 "Unhandled Opcode in getDivRemLibcall");
20830 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20831 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20832 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20833 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20842 "Unhandled Opcode in getDivRemArgList");
20846 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20847 EVT ArgVT =
N->getOperand(i).getValueType();
20852 Args.push_back(Entry);
20860 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20861 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20862 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20863 "Register-based DivRem lowering only");
20864 unsigned Opcode =
Op->getOpcode();
20866 "Invalid opcode for Div/Rem lowering");
20868 EVT VT =
Op->getValueType(0);
20890 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20891 : Subtarget->hasDivideInARMMode();
20892 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20893 Op->getSimpleValueType(0) == MVT::i32) {
20895 const SDValue Dividend =
Op->getOperand(0);
20896 const SDValue Divisor =
Op->getOperand(1);
20897 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20920 if (
getTM().getTargetTriple().isOSWindows())
20923 TargetLowering::CallLoweringInfo CLI(DAG);
20927 Callee, std::move(Args))
20932 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20933 return CallInfo.first;
20939 EVT VT =
N->getValueType(0);
20945 Result[0], Result[1]);
20949 std::vector<Type*> RetTyParams;
20950 Type *RetTyElement;
20960 RetTyParams.push_back(RetTyElement);
20961 RetTyParams.push_back(RetTyElement);
20976 if (
getTM().getTargetTriple().isOSWindows())
20983 Callee, std::move(Args))
20987 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20990 SDNode *ResNode = CallResult.first.getNode();
20997 assert(
getTM().getTargetTriple().isOSWindows() &&
20998 "unsupported target platform");
21006 "no-stack-arg-probe")) {
21010 Chain =
SP.getValue(1);
21027 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
21028 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
21038 bool IsStrict =
Op->isStrictFPOpcode();
21039 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21040 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21042 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
21043 "Unexpected type for custom-lowering FP_EXTEND");
21045 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21046 "With both FP DP and 16, any FP conversion is legal!");
21048 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
21049 "With FP16, 16 to 32 conversion is legal!");
21052 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
21057 Loc,
Op.getValueType(), SrcVal);
21072 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
21073 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
21074 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
21075 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
21079 {DstVT, MVT::Other}, {Chain, SrcVal});
21086 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21087 "Unexpected type for custom-lowering FP_EXTEND");
21088 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21093 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
21097 bool IsStrict =
Op->isStrictFPOpcode();
21099 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21101 EVT DstVT =
Op.getValueType();
21103 if (DstVT == MVT::bf16) {
21104 if (Subtarget->hasBF16() && SrcVT == MVT::f32)
21109 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21112 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
21113 "Unexpected type for custom-lowering FP_ROUND");
21115 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21116 "With both FP DP and 16, any FP conversion is legal!");
21121 if (SrcSz == 32 && Subtarget->hasFP16())
21126 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21127 "Unexpected type for custom-lowering FP_ROUND");
21131 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21143 if (v == 0xffffffff)
21155 bool ForCodeSize)
const {
21156 if (!Subtarget->hasVFP3Base())
21158 if (VT == MVT::f16 && Subtarget->hasFullFP16())
21160 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
21163 if (VT == MVT::f32)
21165 if (VT == MVT::f64 && Subtarget->hasFP64())
21178 case Intrinsic::arm_neon_vld1:
21179 case Intrinsic::arm_neon_vld2:
21180 case Intrinsic::arm_neon_vld3:
21181 case Intrinsic::arm_neon_vld4:
21182 case Intrinsic::arm_neon_vld2lane:
21183 case Intrinsic::arm_neon_vld3lane:
21184 case Intrinsic::arm_neon_vld4lane:
21185 case Intrinsic::arm_neon_vld2dup:
21186 case Intrinsic::arm_neon_vld3dup:
21187 case Intrinsic::arm_neon_vld4dup: {
21190 auto &
DL =
I.getDataLayout();
21191 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21193 Info.ptrVal =
I.getArgOperand(0);
21195 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21202 case Intrinsic::arm_neon_vld1x2:
21203 case Intrinsic::arm_neon_vld1x3:
21204 case Intrinsic::arm_neon_vld1x4: {
21207 auto &
DL =
I.getDataLayout();
21208 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21210 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
21212 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
21218 case Intrinsic::arm_neon_vst1:
21219 case Intrinsic::arm_neon_vst2:
21220 case Intrinsic::arm_neon_vst3:
21221 case Intrinsic::arm_neon_vst4:
21222 case Intrinsic::arm_neon_vst2lane:
21223 case Intrinsic::arm_neon_vst3lane:
21224 case Intrinsic::arm_neon_vst4lane: {
21227 auto &
DL =
I.getDataLayout();
21228 unsigned NumElts = 0;
21229 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21230 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21233 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21236 Info.ptrVal =
I.getArgOperand(0);
21238 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21245 case Intrinsic::arm_neon_vst1x2:
21246 case Intrinsic::arm_neon_vst1x3:
21247 case Intrinsic::arm_neon_vst1x4: {
21250 auto &
DL =
I.getDataLayout();
21251 unsigned NumElts = 0;
21252 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21253 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21256 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21259 Info.ptrVal =
I.getArgOperand(0);
21261 Info.align =
I.getParamAlign(0).valueOrOne();
21267 case Intrinsic::arm_mve_vld2q:
21268 case Intrinsic::arm_mve_vld4q: {
21272 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21274 Info.ptrVal =
I.getArgOperand(0);
21282 case Intrinsic::arm_mve_vst2q:
21283 case Intrinsic::arm_mve_vst4q: {
21286 Type *VecTy =
I.getArgOperand(1)->getType();
21287 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21289 Info.ptrVal =
I.getArgOperand(0);
21297 case Intrinsic::arm_mve_vldr_gather_base:
21298 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21300 Info.ptrVal =
nullptr;
21302 Info.align =
Align(1);
21307 case Intrinsic::arm_mve_vldr_gather_base_wb:
21308 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21310 Info.ptrVal =
nullptr;
21311 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21312 Info.align =
Align(1);
21317 case Intrinsic::arm_mve_vldr_gather_offset:
21318 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21320 Info.ptrVal =
nullptr;
21325 Info.align =
Align(1);
21330 case Intrinsic::arm_mve_vstr_scatter_base:
21331 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21333 Info.ptrVal =
nullptr;
21334 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21335 Info.align =
Align(1);
21340 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21341 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21343 Info.ptrVal =
nullptr;
21344 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21345 Info.align =
Align(1);
21350 case Intrinsic::arm_mve_vstr_scatter_offset:
21351 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21353 Info.ptrVal =
nullptr;
21358 Info.align =
Align(1);
21363 case Intrinsic::arm_ldaex:
21364 case Intrinsic::arm_ldrex: {
21365 auto &
DL =
I.getDataLayout();
21366 Type *ValTy =
I.getParamElementType(0);
21369 Info.ptrVal =
I.getArgOperand(0);
21371 Info.align =
DL.getABITypeAlign(ValTy);
21376 case Intrinsic::arm_stlex:
21377 case Intrinsic::arm_strex: {
21378 auto &
DL =
I.getDataLayout();
21379 Type *ValTy =
I.getParamElementType(1);
21382 Info.ptrVal =
I.getArgOperand(1);
21384 Info.align =
DL.getABITypeAlign(ValTy);
21389 case Intrinsic::arm_stlexd:
21390 case Intrinsic::arm_strexd:
21392 Info.memVT = MVT::i64;
21393 Info.ptrVal =
I.getArgOperand(2);
21395 Info.align =
Align(8);
21400 case Intrinsic::arm_ldaexd:
21401 case Intrinsic::arm_ldrexd:
21403 Info.memVT = MVT::i64;
21404 Info.ptrVal =
I.getArgOperand(0);
21406 Info.align =
Align(8);
21420 assert(Ty->isIntegerTy());
21422 unsigned Bits = Ty->getPrimitiveSizeInBits();
21423 if (Bits == 0 || Bits > 32)
21429 unsigned Index)
const {
21439 if (!Subtarget->hasDataBarrier()) {
21443 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21444 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21445 Builder.getInt32(0), Builder.getInt32(7),
21446 Builder.getInt32(10), Builder.getInt32(5)};
21447 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_mcr,
args);
21456 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_dmb, CDomain);
21477 if (Subtarget->preferISHSTBarriers())
21510 bool has64BitAtomicStore;
21511 if (Subtarget->isMClass())
21512 has64BitAtomicStore =
false;
21513 else if (Subtarget->isThumb())
21514 has64BitAtomicStore = Subtarget->hasV7Ops();
21516 has64BitAtomicStore = Subtarget->hasV6Ops();
21518 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21532 bool has64BitAtomicLoad;
21533 if (Subtarget->isMClass())
21534 has64BitAtomicLoad =
false;
21535 else if (Subtarget->isThumb())
21536 has64BitAtomicLoad = Subtarget->hasV7Ops();
21538 has64BitAtomicLoad = Subtarget->hasV6Ops();
21554 if (Subtarget->isMClass())
21555 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21556 else if (Subtarget->isThumb())
21557 hasAtomicRMW = Subtarget->hasV7Ops();
21559 hasAtomicRMW = Subtarget->hasV6Ops();
21560 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21584 bool HasAtomicCmpXchg;
21585 if (Subtarget->isMClass())
21586 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21587 else if (Subtarget->isThumb())
21588 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21590 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21592 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21599 return InsertFencesForAtomic;
21604 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21610 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21611 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21613 RTLIB::LibcallImpl SecurityCookieVar =
21614 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21615 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21616 SecurityCookieVar != RTLIB::Unsupported) {
21627 F->addParamAttr(0, Attribute::AttrKind::InReg);
21634 unsigned &
Cost)
const {
21636 if (!Subtarget->hasNEON())
21665 unsigned Opcode =
Op.getOpcode();
21667 case ARMISD::VORRIMM:
21668 case ARMISD::VBICIMM:
21672 Op, DemandedElts, DAG, Kind, ConsiderFlags,
Depth);
21676 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21680 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21685 if (!Subtarget->hasV7Ops())
21691 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21693 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21701 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21710 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21716 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21718 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21721 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21723 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21724 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21725 if (!Subtarget->isLittle())
21727 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21728 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21729 return Builder.CreateOr(
21730 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21734 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21735 CallInst *CI = Builder.CreateIntrinsicWithoutFolding(
Int, Tys, Addr);
21738 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21739 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21744 if (!Subtarget->hasV7Ops())
21746 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21752 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21760 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21763 Value *
Lo = Builder.CreateTrunc(Val, Int32Ty,
"lo");
21764 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32), Int32Ty,
"hi");
21765 if (!Subtarget->isLittle())
21767 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21770 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21774 CallInst *CI = Builder.CreateCall(
21775 Strex, {Builder.CreateZExtOrBitCast(
21785 return Subtarget->isMClass();
21793 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21800 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21803 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21811 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21819 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21822 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21827 if (Subtarget->hasNEON() && VecSize == 64)
21829 return VecSize % 128 == 0;
21833 if (Subtarget->hasNEON())
21835 if (Subtarget->hasMVEIntegerOps())
21855 "Invalid interleave factor");
21856 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21858 "Unmatched number of shufflevectors and indices");
21863 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21866 Type *EltTy = VecTy->getElementType();
21869 Align Alignment = LI->getAlign();
21887 Value *BaseAddr = LI->getPointerOperand();
21889 if (NumLoads > 1) {
21893 VecTy->getNumElements() / NumLoads);
21899 if (Subtarget->hasNEON()) {
21900 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21901 Type *Tys[] = {VecTy, PtrTy};
21902 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21903 Intrinsic::arm_neon_vld3,
21904 Intrinsic::arm_neon_vld4};
21907 Ops.push_back(BaseAddr);
21908 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21910 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21913 assert((Factor == 2 || Factor == 4) &&
21914 "expected interleave factor of 2 or 4 for MVE");
21916 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21917 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21918 Type *Tys[] = {VecTy, PtrTy};
21921 Ops.push_back(BaseAddr);
21922 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21932 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21936 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21937 VecTy->getNumElements() * Factor);
21943 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21945 unsigned Index = Indices[i];
21947 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21951 SubVec = Builder.CreateIntToPtr(
21955 SubVecs[SV].push_back(SubVec);
21964 auto &SubVec = SubVecs[SVI];
21967 SVI->replaceAllUsesWith(WideVec);
22003 const APInt &GapMask)
const {
22005 "Invalid interleave factor");
22010 "Unexpected mask on store");
22013 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
22015 unsigned LaneLen = VecTy->getNumElements() / Factor;
22016 Type *EltTy = VecTy->getElementType();
22020 Align Alignment =
SI->getAlign();
22037 Type *IntTy =
DL.getIntPtrType(EltTy);
22042 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
22043 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
22049 Value *BaseAddr =
SI->getPointerOperand();
22051 if (NumStores > 1) {
22054 LaneLen /= NumStores;
22064 if (Subtarget->hasNEON()) {
22065 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
22066 Intrinsic::arm_neon_vst3,
22067 Intrinsic::arm_neon_vst4};
22068 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22069 Type *Tys[] = {PtrTy, SubVecTy};
22072 Ops.push_back(BaseAddr);
22074 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
22075 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
22077 assert((Factor == 2 || Factor == 4) &&
22078 "expected interleave factor of 2 or 4 for MVE");
22080 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
22081 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22082 Type *Tys[] = {PtrTy, SubVecTy};
22085 Ops.push_back(BaseAddr);
22087 for (
unsigned F = 0;
F < Factor;
F++) {
22088 Ops.push_back(Builder.getInt32(
F));
22089 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
22095 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
22098 if (StoreCount > 0)
22099 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
22100 BaseAddr, LaneLen * Factor);
22105 for (
unsigned i = 0; i < Factor; i++) {
22106 unsigned IdxI = StoreCount * LaneLen * Factor + i;
22107 if (Mask[IdxI] >= 0) {
22108 Shuffles.
push_back(Builder.CreateShuffleVector(
22111 unsigned StartMask = 0;
22112 for (
unsigned j = 1; j < LaneLen; j++) {
22113 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
22114 if (Mask[IdxJ * Factor + IdxI] >= 0) {
22115 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
22125 Shuffles.
push_back(Builder.CreateShuffleVector(
22146 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
22150 Members += SubMembers;
22156 Members += SubMembers * AT->getNumElements();
22157 }
else if (Ty->isFloatTy()) {
22162 }
else if (Ty->isDoubleTy()) {
22174 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
22176 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
22178 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
22191 return (Members > 0 && Members <= 4);
22197 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
22199 return ABITypeAlign;
22204 assert(StackAlign &&
"data layout string is missing stack alignment");
22205 return std::min(ABITypeAlign, *StackAlign);
22214 if (getEffectiveCallingConv(CallConv, isVarArg) !=
22223 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
22224 return IsHA || IsIntArray;
22228 const Constant *PersonalityFn)
const {
22236 const Constant *PersonalityFn)
const {
22249void ARMTargetLowering::insertCopiesSplitCSR(
22253 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22263 RC = &ARM::GPRRegClass;
22264 else if (ARM::DPRRegClass.
contains(*
I))
22265 RC = &ARM::DPRRegClass;
22275 assert(Entry->getParent()->getFunction().hasFnAttribute(
22276 Attribute::NoUnwind) &&
22277 "Function should be nounwind in insertCopiesSplitCSR!");
22278 Entry->addLiveIn(*
I);
22283 for (
auto *Exit : Exits)
22285 TII->get(TargetOpcode::COPY), *
I)
22296 return Subtarget->hasMVEIntegerOps();
22306 unsigned NumElements = VTy->getNumElements();
22313 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22314 return Subtarget->hasMVEFloatOps();
22319 return Subtarget->hasMVEIntegerOps() &&
22320 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22321 ScalarTy->isIntegerTy(32));
22325 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22336 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22338 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22340 if (TyWidth > 128) {
22341 int Stride = Ty->getNumElements() / 2;
22345 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22347 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22348 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22349 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22350 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22351 Value *LowerSplitAcc =
nullptr;
22352 Value *UpperSplitAcc =
nullptr;
22355 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22356 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22360 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22362 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22364 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22365 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22372 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22375 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22377 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22378 {ConstRotation, InputB, InputA});
22383 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22386 ConstRotation = ConstantInt::get(IntTy, 0);
22388 ConstRotation = ConstantInt::get(IntTy, 1);
22390 if (!ConstRotation)
22393 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22394 {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 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< 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 ...
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static 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)
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 from min(max(fptoi)) satur...
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
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 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.
static bool isWeakForLinker(LinkageTypes Linkage)
Whether the definition of this global may be replaced at link time.
@ 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(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
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.
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 getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
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
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)
@ SECREL
Thread Pointer Offset.
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
TOF
Target Operand Flag enum.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2Offset(unsigned AM2Opc)
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
AddrOpc getAM2Op(unsigned AM2Opc)
bool isBitFieldInvertedMask(unsigned v)
const unsigned FPStatusBits
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.
@ 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.
@ 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
@ 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...
@ 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.
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...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
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.
bool isUnknown() const
Returns true if we don't know any bits.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
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.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
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)