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>();
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);
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);
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) ||
4513 if (ST.isThumb1Only() || !
Op.hasOneUse())
4516 unsigned Opc =
Op.getOpcode();
4519 return ShiftAmt->getZExtValue() <= 31 ? 1 : 0;
4522 return ST.isThumb() ? 0 : 1;
4530 return ST.isThumb() ? 0 : 1;
4540 const SDLoc &dl)
const {
4542 unsigned C = RHSC->getZExtValue();
4600 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4604 unsigned Mask =
LHS.getConstantOperandVal(1);
4606 uint64_t RHSV = RHSC->getZExtValue();
4607 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4609 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4623 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4626 LHS.getConstantOperandVal(1) < 31) {
4627 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4637 unsigned CompareType;
4640 CompareType = ARMISD::CMP;
4645 CompareType = ARMISD::CMPZ;
4654 if (CompareType != ARMISD::CMPZ &&
isCMN(
RHS, CC, DAG)) {
4655 CompareType = ARMISD::CMN;
4657 }
else if (CompareType != ARMISD::CMPZ &&
isCMN(
LHS, CC, DAG)) {
4658 CompareType = ARMISD::CMN;
4672 if (CompareType == ARMISD::CMP)
4700 bool Signaling)
const {
4701 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4707 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4716std::pair<SDValue, SDValue>
4719 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4731 switch (
Op.getOpcode()) {
4783 return std::make_pair(
Value, OverflowCmp);
4796 return Cmp.getValue(1);
4824 return DAG.
getNode(ARMISD::CMOV,
DL, VT, Zero, One, ARMcc, Flags);
4836 EVT VT =
Op.getValueType();
4837 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4840 switch (
Op.getOpcode()) {
4854 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4860 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4863 ARMcc, OverflowCmp);
4873 EVT VT =
Op.getValueType();
4874 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4884 switch (
Op->getOpcode()) {
4886 NewOpcode = ARMISD::UQADD8b;
4889 NewOpcode = ARMISD::QADD8b;
4892 NewOpcode = ARMISD::UQSUB8b;
4895 NewOpcode = ARMISD::QSUB8b;
4900 switch (
Op->getOpcode()) {
4902 NewOpcode = ARMISD::UQADD16b;
4905 NewOpcode = ARMISD::QADD16b;
4908 NewOpcode = ARMISD::UQSUB16b;
4911 NewOpcode = ARMISD::QSUB16b;
4919 DAG.
getNode(NewOpcode, dl, MVT::i32,
4930 unsigned Opc =
Cond.getOpcode();
4932 if (
Cond.getResNo() == 1 &&
4940 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4941 EVT VT =
Op.getValueType();
4943 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4951 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4952 const ConstantSDNode *CMOVTrue =
4954 const ConstantSDNode *CMOVFalse =
4957 if (CMOVTrue && CMOVFalse) {
4963 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
4965 False = SelectFalse;
4966 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
4972 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
4973 Cond.getOperand(3), DAG);
4983 bool &swpCmpOps,
bool &swpVselOps) {
5011 swpCmpOps = !swpCmpOps;
5012 swpVselOps = !swpVselOps;
5035 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5037 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5039 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5053 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5074 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5076 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5097 EVT VT =
Op.getValueType();
5119 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5132 int64_t PosVal = std::max(Val1, Val2);
5133 int64_t NegVal = std::min(Val1, Val2);
5145 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5148 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5180 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5185 if (*K != KTmp || V != VTmp)
5196bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5198 return !Subtarget->hasVFP2Base();
5200 return !Subtarget->hasFP64();
5202 return !Subtarget->hasFullFP16();
5210 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5218 if (TVal == ~FVal) {
5219 Opcode = ARMISD::CSINV;
5220 }
else if (TVal == ~FVal + 1) {
5221 Opcode = ARMISD::CSNEG;
5222 }
else if (TVal + 1 == FVal) {
5223 Opcode = ARMISD::CSINC;
5224 }
else if (TVal == FVal + 1) {
5225 Opcode = ARMISD::CSINC;
5228 InvertCond = !InvertCond;
5235 if (Opcode != ARMISD::CSINC &&
5239 InvertCond = !InvertCond;
5245 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5248 InvertCond = !InvertCond;
5255 EVT VT =
Op.getValueType();
5259 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5271 if (VT == MVT::i32 &&
5290 if (
Op.getValueType().isInteger()) {
5298 LHS.getValueType() ==
RHS.getValueType()) {
5299 EVT VT =
LHS.getValueType();
5305 Shift = DAG.
getNOT(dl, Shift, VT);
5317 if (
LHS.getValueType() == MVT::i32) {
5321 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5327 EVT VT =
Op.getValueType();
5328 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5332 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5337 if (!
RHS.getNode()) {
5343 if (
LHS.getValueType() == MVT::i32) {
5354 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5355 TrueVal.getValueType() == MVT::f32 ||
5356 TrueVal.getValueType() == MVT::f64)) {
5370 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5380 if (Subtarget->hasFPARMv8Base() &&
5382 (
TrueVal.getValueType() == MVT::f16 ||
5383 TrueVal.getValueType() == MVT::f32 ||
5384 TrueVal.getValueType() == MVT::f64)) {
5385 bool swpCmpOps =
false;
5386 bool swpVselOps =
false;
5400 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5403 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5413 if (!
N->hasOneUse())
5416 if (!
N->getNumValues())
5418 EVT VT =
Op.getValueType();
5419 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5436 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5437 Ld->getPointerInfo(), Ld->getAlign(),
5438 Ld->getMemOperand()->getFlags());
5454 SDValue Ptr = Ld->getBasePtr();
5456 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5457 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5462 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5463 Ld->getPointerInfo().getWithOffset(4),
5465 Ld->getMemOperand()->getFlags());
5483 bool LHSSeenZero =
false;
5485 bool RHSSeenZero =
false;
5487 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5498 if (
LHS.getValueType() == MVT::f32) {
5504 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5516 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5517 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5532 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5551 unsigned Opc =
Cond.getOpcode();
5553 !Subtarget->isThumb1Only();
5554 if (
Cond.getResNo() == 1 &&
5564 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5569 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5584 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5589 if (!
RHS.getNode()) {
5597 unsigned Opc =
LHS.getOpcode();
5599 !Subtarget->isThumb1Only();
5611 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5618 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5622 if (
LHS.getValueType() == MVT::i32) {
5625 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5628 SDNodeFlags
Flags =
Op->getFlags();
5629 if (
Flags.hasNoNaNs() &&
5634 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5648 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5662 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5665 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5670 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5671 Addr,
Op.getOperand(2), JTI);
5675 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5679 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5682 DAG.
getLoad(PTy, dl, Chain, Addr,
5685 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5690 EVT VT =
Op.getValueType();
5693 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5694 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5702 const EVT OpTy =
Op.getOperand(0).getValueType();
5703 if (
OpTy == MVT::v4f32)
5705 else if (
OpTy == MVT::v4f16 && HasFullFP16)
5707 else if (
OpTy == MVT::v8f16 && HasFullFP16)
5712 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5715 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5720 EVT VT =
Op.getValueType();
5724 bool IsStrict =
Op->isStrictFPOpcode();
5725 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5727 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5740 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5741 CallOptions, Loc, Chain);
5751 Loc,
Op.getValueType(), SrcVal);
5760 EVT VT =
Op.getValueType();
5762 EVT FromVT =
Op.getOperand(0).getValueType();
5764 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5766 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5767 Subtarget->hasFP64())
5769 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5770 Subtarget->hasFullFP16())
5772 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5773 Subtarget->hasMVEFloatOps())
5775 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5776 Subtarget->hasMVEFloatOps())
5779 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5796 EVT VT =
Op.getValueType();
5799 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5805 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5806 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5807 "Invalid type for custom lowering!");
5812 if (VT == MVT::v4f32)
5813 DestVecType = MVT::v4i32;
5814 else if (VT == MVT::v4f16 && HasFullFP16)
5815 DestVecType = MVT::v4i16;
5816 else if (VT == MVT::v8f16 && HasFullFP16)
5817 DestVecType = MVT::v8i16;
5823 switch (
Op.getOpcode()) {
5835 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5840 EVT VT =
Op.getValueType();
5843 if (isUnsupportedFloatingType(VT)) {
5853 CallOptions, SDLoc(
Op)).first;
5864 EVT VT =
Op.getValueType();
5868 bool UseNEON = !InGPR && Subtarget->hasNEON();
5875 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5882 if (SrcVT == MVT::f32) {
5885 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5888 }
else if (VT == MVT::f32)
5889 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5904 if (VT == MVT::f32) {
5916 if (SrcVT == MVT::f64)
5925 if (VT == MVT::f32) {
5938 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5946 EVT VT =
Op.getValueType();
5948 unsigned Depth =
Op.getConstantOperandVal(0);
5950 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5954 MachinePointerInfo());
5963 const ARMBaseRegisterInfo &ARI =
5964 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
5969 EVT VT =
Op.getValueType();
5971 unsigned Depth =
Op.getConstantOperandVal(0);
5976 MachinePointerInfo());
5984 return StringSwitch<Register>(
RegName)
5985 .Case(
"sp", ARM::SP)
5996 assert(
N->getValueType(0) == MVT::i64
5997 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6000 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6040 const APInt &APIntIndex = Index->getAPIntValue();
6042 NewIndex *= APIntIndex;
6071 EVT SrcVT =
Op.getValueType();
6072 EVT DstVT =
N->getValueType(0);
6074 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6075 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6076 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6079 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6080 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6081 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6088 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6100 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6108 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6110 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6112 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6132 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6141 EVT VT =
Op.getValueType();
6163 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6173 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6184 EVT VT =
Op.getValueType();
6205 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6226 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6278 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6306 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6336 EVT VT =
N->getValueType(0);
6337 if (VT.
isVector() && ST->hasNEON()) {
6346 if (ElemTy == MVT::i8) {
6354 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6357 unsigned NumBits = ElemTy.getSizeInBits();
6359 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6369 if (ElemTy == MVT::i64) {
6382 if (!ST->hasV6T2Ops())
6391 EVT VT =
N->getValueType(0);
6394 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6395 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6396 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6397 "Unexpected type for custom ctpop lowering");
6405 unsigned EltSize = 8;
6428 Op =
Op.getOperand(0);
6430 APInt SplatBits, SplatUndef;
6431 unsigned SplatBitSize;
6434 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6436 SplatBitSize > ElementBits)
6447 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6451 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6462 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6467 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6468 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6477 EVT VT =
N->getValueType(0);
6492 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6494 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6499 "unexpected vector shift opcode");
6501 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6502 unsigned VShiftOpc =
6503 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6504 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6510 EVT ShiftVT =
N->getOperand(1).getValueType();
6513 unsigned VShiftOpc =
6514 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6515 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6520 EVT VT =
N->getValueType(0);
6529 "Unknown shift to lower!");
6531 unsigned ShOpc =
N->getOpcode();
6532 if (ST->hasMVEIntegerOps()) {
6534 unsigned ShPartsOpc = ARMISD::LSLL;
6555 ShPartsOpc = ARMISD::LSRL;
6557 ShPartsOpc = ARMISD::ASRL;
6562 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6576 if (ST->isThumb1Only())
6581 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6585 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6589 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6597 bool Invert =
false;
6604 EVT VT =
Op.getValueType();
6612 assert(ST->hasMVEIntegerOps() &&
6613 "No hardware support for integer vector comparison!");
6615 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6636 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6640 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6650 switch (SetCCOpcode) {
6654 if (ST->hasMVEFloatOps()) {
6657 Invert =
true; [[fallthrough]];
6662 case ISD::SETLT: Swap =
true; [[fallthrough]];
6666 case ISD::SETLE: Swap =
true; [[fallthrough]];
6682 Result = DAG.
getNOT(dl, Result, VT);
6685 case ISD::SETUO: Invert =
true; [[fallthrough]];
6694 Result = DAG.
getNOT(dl, Result, VT);
6700 switch (SetCCOpcode) {
6703 if (ST->hasMVEIntegerOps()) {
6706 Invert =
true; [[fallthrough]];
6709 case ISD::SETLT: Swap =
true; [[fallthrough]];
6711 case ISD::SETLE: Swap =
true; [[fallthrough]];
6728 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6731 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6736 Result = DAG.
getNOT(dl, Result, VT);
6761 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6764 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6770 Result = DAG.
getNOT(dl, Result, VT);
6779 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6796 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6807 unsigned OpCmode, Imm;
6818 switch (SplatBitSize) {
6823 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6826 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6831 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6832 if ((SplatBits & ~0xff) == 0) {
6838 if ((SplatBits & ~0xff00) == 0) {
6841 Imm = SplatBits >> 8;
6851 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6852 if ((SplatBits & ~0xff) == 0) {
6858 if ((SplatBits & ~0xff00) == 0) {
6861 Imm = SplatBits >> 8;
6864 if ((SplatBits & ~0xff0000) == 0) {
6867 Imm = SplatBits >> 16;
6870 if ((SplatBits & ~0xff000000) == 0) {
6873 Imm = SplatBits >> 24;
6880 if ((SplatBits & ~0xffff) == 0 &&
6881 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6884 Imm = SplatBits >> 8;
6892 if ((SplatBits & ~0xffffff) == 0 &&
6893 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6896 Imm = SplatBits >> 16;
6912 unsigned ImmMask = 1;
6914 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6915 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6917 }
else if ((SplatBits & BitMask) != 0) {
6926 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6940 EVT VT =
Op.getValueType();
6941 bool IsDouble = (VT == MVT::f64);
6947 if (
ST->genExecuteOnly()) {
6949 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6950 "Unexpected architecture");
6968 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
6973 if (!
ST->hasVFP3Base())
6978 if (IsDouble && !Subtarget->hasFP64())
6985 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7003 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7012 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7066 unsigned ExpectedElt = Imm;
7067 for (
unsigned i = 1; i < NumElts; ++i) {
7071 if (ExpectedElt == NumElts)
7074 if (M[i] < 0)
continue;
7075 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7083 bool &ReverseVEXT,
unsigned &Imm) {
7085 ReverseVEXT =
false;
7096 unsigned ExpectedElt = Imm;
7097 for (
unsigned i = 1; i < NumElts; ++i) {
7101 if (ExpectedElt == NumElts * 2) {
7106 if (M[i] < 0)
continue;
7107 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7122 return VT == MVT::v8i8 && M.size() == 8;
7127 if (Mask.size() == Elements * 2)
7128 return Index / Elements;
7129 return Mask[Index] == 0 ? 0 : 1;
7159 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7167 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7169 for (
unsigned j = 0; j < NumElts; j += 2) {
7170 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7171 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7176 if (M.size() == NumElts*2)
7191 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7194 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7196 for (
unsigned j = 0; j < NumElts; j += 2) {
7197 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7198 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7203 if (M.size() == NumElts*2)
7223 if (M.size() != NumElts && M.size() != NumElts*2)
7226 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7228 for (
unsigned j = 0; j < NumElts; ++j) {
7229 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7234 if (M.size() == NumElts*2)
7253 if (M.size() != NumElts && M.size() != NumElts*2)
7256 unsigned Half = NumElts / 2;
7257 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7259 for (
unsigned j = 0; j < NumElts; j += Half) {
7260 unsigned Idx = WhichResult;
7261 for (
unsigned k = 0; k < Half; ++k) {
7262 int MIdx = M[i + j + k];
7263 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7270 if (M.size() == NumElts*2)
7294 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7297 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7299 unsigned Idx = WhichResult * NumElts / 2;
7300 for (
unsigned j = 0; j < NumElts; j += 2) {
7301 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7302 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7308 if (M.size() == NumElts*2)
7327 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7330 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7332 unsigned Idx = WhichResult * NumElts / 2;
7333 for (
unsigned j = 0; j < NumElts; j += 2) {
7334 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7335 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7341 if (M.size() == NumElts*2)
7354 unsigned &WhichResult,
7357 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7358 return ARMISD::VTRN;
7359 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7360 return ARMISD::VUZP;
7361 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7362 return ARMISD::VZIP;
7366 return ARMISD::VTRN;
7368 return ARMISD::VUZP;
7370 return ARMISD::VZIP;
7379 if (NumElts != M.size())
7383 for (
unsigned i = 0; i != NumElts; ++i)
7384 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7393 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7401 int Ofs = Top ? 1 : 0;
7402 int Upper = SingleSource ? 0 : NumElts;
7403 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7404 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7406 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7415 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7424 unsigned Offset = Top ? 0 : 1;
7425 unsigned N = SingleSource ? 0 : NumElts;
7426 for (
unsigned i = 0; i < NumElts; i += 2) {
7427 if (M[i] >= 0 && M[i] != (
int)i)
7429 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7438 if (NumElts != M.size())
7446 unsigned Off0 = rev ? NumElts / 2 : 0;
7447 unsigned Off1 = rev ? 0 : NumElts / 2;
7448 for (
unsigned i = 0; i < NumElts; i += 2) {
7449 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7451 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7467 if (!ST->hasMVEFloatOps())
7472 if (VT != MVT::v8f16)
7493 for (
unsigned i = 1; i < 4; i++) {
7508 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7520 if (!ST->hasMVEFloatOps())
7525 if (VT != MVT::v4f32)
7541 for (
unsigned i = 1; i < 4; i++) {
7552 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7564 Val =
N->getAsZExtVal();
7566 if (ST->isThumb1Only()) {
7567 if (Val <= 255 || ~Val <= 255)
7579 EVT VT =
Op.getValueType();
7581 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7585 unsigned BitsPerBool;
7589 }
else if (NumElts == 4) {
7592 }
else if (NumElts == 8) {
7595 }
else if (NumElts == 16) {
7606 return U.get().isUndef() || U.get() == FirstOp;
7610 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7614 unsigned Bits32 = 0;
7615 for (
unsigned i = 0; i < NumElts; ++i) {
7619 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7621 Bits32 |= BoolMask << (i * BitsPerBool);
7627 for (
unsigned i = 0; i < NumElts; ++i) {
7640 if (!ST->hasMVEIntegerOps())
7644 EVT VT =
Op.getValueType();
7654 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7658 for (
unsigned I = 2;
I < NumElts;
I++) {
7674 switch (
N->getOpcode()) {
7685 return N->getOperand(1).getNode() ==
Op;
7687 switch (
N->getConstantOperandVal(0)) {
7688 case Intrinsic::arm_mve_add_predicated:
7689 case Intrinsic::arm_mve_mul_predicated:
7690 case Intrinsic::arm_mve_qadd_predicated:
7691 case Intrinsic::arm_mve_vhadd:
7692 case Intrinsic::arm_mve_hadd_predicated:
7693 case Intrinsic::arm_mve_vqdmulh:
7694 case Intrinsic::arm_mve_qdmulh_predicated:
7695 case Intrinsic::arm_mve_vqrdmulh:
7696 case Intrinsic::arm_mve_qrdmulh_predicated:
7697 case Intrinsic::arm_mve_vqdmull:
7698 case Intrinsic::arm_mve_vqdmull_predicated:
7700 case Intrinsic::arm_mve_sub_predicated:
7701 case Intrinsic::arm_mve_qsub_predicated:
7702 case Intrinsic::arm_mve_vhsub:
7703 case Intrinsic::arm_mve_hsub_predicated:
7704 return N->getOperand(2).getNode() ==
Op;
7719 EVT VT =
Op.getValueType();
7727 APInt SplatBits, SplatUndef;
7728 unsigned SplatBitSize;
7730 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7737 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7739 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7740 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7741 : SplatBitSize == 16 ? MVT::v8i16
7745 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7748 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7749 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7754 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7758 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7762 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7764 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7768 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7772 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7776 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7782 if (
ST->hasMVEIntegerOps() &&
7783 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7784 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7785 : SplatBitSize == 16 ? MVT::v8i16
7789 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7802 bool isOnlyLowElement =
true;
7803 bool usesOnlyOneValue =
true;
7804 bool hasDominantValue =
false;
7809 DenseMap<SDValue, unsigned> ValueCounts;
7811 for (
unsigned i = 0; i < NumElts; ++i) {
7816 isOnlyLowElement =
false;
7820 unsigned &
Count = ValueCounts[
V];
7823 if (++
Count > (NumElts / 2)) {
7824 hasDominantValue =
true;
7828 if (ValueCounts.
size() != 1)
7829 usesOnlyOneValue =
false;
7830 if (!
Value.getNode() && !ValueCounts.
empty())
7833 if (ValueCounts.
empty())
7839 (VT != MVT::v8f16 ||
ST->hasFullFP16()))
7846 if (hasDominantValue && EltSize <= 32) {
7855 ConstantSDNode *constIndex;
7862 if (VT !=
Value->getOperand(0).getValueType()) {
7865 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7870 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7875 if (!usesOnlyOneValue) {
7878 for (
unsigned I = 0;
I < NumElts; ++
I) {
7883 Ops.push_back(
Op.getOperand(
I));
7893 assert(FVT == MVT::f32 || FVT == MVT::f16);
7894 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7895 for (
unsigned i = 0; i < NumElts; ++i)
7900 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7904 if (usesOnlyOneValue) {
7907 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7931 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7951 if (EltSize >= 32) {
7957 for (
unsigned i = 0; i < NumElts; ++i)
7970 (VT == MVT::v8f16 && !
ST->hasFullFP16())) {
7972 for (
unsigned i = 0 ; i < NumElts; ++i) {
7991 EVT VT =
Op.getValueType();
7994 struct ShuffleSourceInfo {
7996 unsigned MinElt = std::numeric_limits<unsigned>::max();
7997 unsigned MaxElt = 0;
8007 int WindowScale = 1;
8009 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8017 for (
unsigned i = 0; i < NumElts; ++i) {
8032 SDValue SourceVec =
V.getOperand(0);
8034 if (Source == Sources.
end())
8038 unsigned EltNo =
V.getConstantOperandVal(1);
8045 if (Sources.
size() > 2)
8051 for (
auto &Source : Sources) {
8052 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8053 if (SrcEltTy.
bitsLT(SmallestEltTy))
8054 SmallestEltTy = SrcEltTy;
8056 unsigned ResMultiplier =
8064 for (
auto &Src : Sources) {
8065 EVT SrcVT = Src.ShuffleVec.getValueType();
8069 if (SrcVTSize == VTSize)
8078 if (SrcVTSize < VTSize) {
8079 if (2 * SrcVTSize != VTSize)
8085 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8089 if (SrcVTSize != 2 * VTSize)
8092 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8097 if (Src.MinElt >= NumSrcElts) {
8102 Src.WindowBase = -NumSrcElts;
8103 }
else if (Src.MaxElt < NumSrcElts) {
8117 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8120 Src.WindowBase = -Src.MinElt;
8127 for (
auto &Src : Sources) {
8128 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8129 if (SrcEltTy == SmallestEltTy)
8132 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8134 Src.WindowBase *= Src.WindowScale;
8139 for (
auto Src : Sources)
8140 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8148 if (
Entry.isUndef())
8157 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8160 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8164 int *LaneMask = &
Mask[i * ResMultiplier];
8166 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8167 ExtractBase += NumElts * (Src - Sources.begin());
8168 for (
int j = 0;
j < LanesDefined; ++
j)
8169 LaneMask[j] = ExtractBase + j;
8175 assert(Sources.size() <= 2 &&
"Too many sources!");
8178 for (
unsigned i = 0; i < Sources.size(); ++i)
8185 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8207 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8227 unsigned PFIndexes[4];
8228 for (
unsigned i = 0; i != 4; ++i) {
8232 PFIndexes[i] = M[i];
8236 unsigned PFTableIndex =
8237 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8239 unsigned Cost = (PFEntry >> 30);
8245 bool ReverseVEXT, isV_UNDEF;
8246 unsigned Imm, WhichResult;
8249 if (EltSize >= 32 ||
8256 else if (Subtarget->hasNEON() &&
8261 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8264 else if (Subtarget->hasMVEIntegerOps() &&
8268 else if (Subtarget->hasMVEIntegerOps() &&
8282 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8283 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8284 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8287 if (LHSID == (1*9+2)*9+3)
return LHS;
8288 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8302 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8305 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8308 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8313 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8318 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8345 for (
int I : ShuffleMask)
8349 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8,
V1,
8352 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8,
V1, V2,
8358 EVT VT =
Op.getValueType();
8360 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8361 "Expect an v8i16/v16i8 type");
8367 std::vector<int> NewMask;
8371 NewMask.push_back(i);
8401 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8411 if (VT != MVT::v16i1)
8412 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8427 EVT VT =
Op.getValueType();
8431 assert(ST->hasMVEIntegerOps() &&
8432 "No support for vector shuffle of boolean predicates");
8442 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8458 "Expected identical vector type in expanded i1 shuffle!");
8462 PredAsVector2, ShuffleMask);
8467 if (VT == MVT::v2i1) {
8468 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8471 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8473 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8484 EVT VT =
Op.getValueType();
8488 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8489 "Unexpected vector type");
8491 int QuarterSize = NumElts / 4;
8500 for (
int i = 0; i <
Length; i++) {
8501 if (ShuffleMask[Start + i] >= 0) {
8502 if (ShuffleMask[Start + i] %
Length != i)
8504 MovIdx = ShuffleMask[Start + i] /
Length;
8512 for (
int i = 1; i <
Length; i++) {
8513 if (ShuffleMask[Start + i] >= 0 &&
8514 (ShuffleMask[Start + i] /
Length != MovIdx ||
8515 ShuffleMask[Start + i] %
Length != i))
8521 for (
int Part = 0; Part < 4; ++Part) {
8523 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8537 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8542 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8544 for (
int Part = 0; Part < 4; ++Part)
8545 for (
int i = 0; i < QuarterSize; i++)
8547 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8549 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8552 for (
int Part = 0; Part < 4; ++Part)
8568 EVT VT =
Op.getValueType();
8580 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8584 if (Mask[i] != i + BaseOffset) {
8585 if (OffElement == -1)
8591 return NonUndef > 2 && OffElement != -1;
8595 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8597 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8608 ShuffleMask[OffElement] < (
int)NumElts ?
V1 : V2,
8619 EVT VT =
Op.getValueType();
8623 if (ST->hasMVEIntegerOps() && EltSize == 1)
8634 if (EltSize <= 32) {
8638 if (Lane == -1) Lane = 0;
8642 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8649 bool IsScalarToVector =
true;
8650 for (
unsigned i = 1, e =
V1.getNumOperands(); i != e; ++i)
8651 if (!
V1.getOperand(i).isUndef()) {
8652 IsScalarToVector =
false;
8655 if (IsScalarToVector)
8656 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8658 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
V1,
8662 bool ReverseVEXT =
false;
8664 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8667 return DAG.
getNode(ARMISD::VEXT, dl, VT,
V1, V2,
8672 return DAG.
getNode(ARMISD::VREV64, dl, VT,
V1);
8674 return DAG.
getNode(ARMISD::VREV32, dl, VT,
V1);
8676 return DAG.
getNode(ARMISD::VREV16, dl, VT,
V1);
8688 unsigned WhichResult = 0;
8689 bool isV_UNDEF =
false;
8690 if (ST->hasNEON()) {
8692 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8699 if (ST->hasMVEIntegerOps()) {
8701 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2,
V1,
8704 return DAG.
getNode(ARMISD::VMOVN, dl, VT,
V1, V2,
8734 }) &&
"Unexpected shuffle index into UNDEF operand!");
8737 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8740 assert((WhichResult == 0) &&
8741 "In-place shuffle of concat can only have one result!");
8750 if (ST->hasMVEIntegerOps() && EltSize <= 32 &&
8751 (ST->hasFullFP16() || VT != MVT::v8f16)) {
8755 for (
bool Top : {
false,
true}) {
8756 for (
bool SingleSource : {
false,
true}) {
8757 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8762 SingleSource ?
V1 : V2);
8778 unsigned PFIndexes[4];
8779 for (
unsigned i = 0; i != 4; ++i) {
8780 if (ShuffleMask[i] < 0)
8783 PFIndexes[i] = ShuffleMask[i];
8787 unsigned PFTableIndex =
8788 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8790 unsigned Cost = (PFEntry >> 30);
8796 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8797 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8807 if (EltSize >= 32) {
8815 for (
unsigned i = 0; i < NumElts; ++i) {
8816 if (ShuffleMask[i] < 0)
8820 ShuffleMask[i] < (
int)NumElts ?
V1 : V2,
8828 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8832 if (ST->hasNEON() && VT == MVT::v8i8)
8836 if (ST->hasMVEIntegerOps())
8841 if (VT == MVT::v8f16 && !ST->hasFullFP16()) {
8843 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(0));
8845 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(1));
8847 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuf);
8855 EVT VecVT =
Op.getOperand(0).getValueType();
8858 assert(ST->hasMVEIntegerOps() &&
8859 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8862 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8863 unsigned Lane =
Op.getConstantOperandVal(2);
8864 unsigned LaneWidth =
8866 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8871 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8884 if (Subtarget->hasMVEIntegerOps() &&
8885 Op.getValueType().getScalarSizeInBits() == 1)
8909 IVecIn, IElt, Lane);
8918 EVT VecVT =
Op.getOperand(0).getValueType();
8921 assert(ST->hasMVEIntegerOps() &&
8922 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8925 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8926 unsigned Lane =
Op.getConstantOperandVal(1);
8927 unsigned LaneWidth =
8949 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8958 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8959 "Unexpected custom CONCAT_VECTORS lowering");
8961 "Unexpected custom CONCAT_VECTORS lowering");
8962 assert(ST->hasMVEIntegerOps() &&
8963 "CONCAT_VECTORS lowering only supported for MVE");
8966 EVT Op1VT =
V1.getValueType();
8967 EVT Op2VT = V2.getValueType();
8968 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8969 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8970 "Unexpected i1 concat operations!");
8983 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8988 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8997 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8998 EVT NewVT = NewV.getValueType();
8999 EVT ConcatVT = ConVec.getValueType();
9000 unsigned ExtScale = 1;
9001 if (NewVT == MVT::v2f64) {
9002 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
9015 ConVec = ExtractInto(NewV1, ConVec, j);
9016 ConVec = ExtractInto(NewV2, ConVec, j);
9020 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
9026 while (ConcatOps.
size() > 1) {
9027 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
9030 ConcatOps[
I / 2] = ConcatPair(
V1, V2);
9034 return ConcatOps[0];
9039 EVT VT =
Op->getValueType(0);
9045 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9046 "unexpected CONCAT_VECTORS");
9067 EVT VT =
Op.getValueType();
9068 EVT Op1VT =
V1.getValueType();
9073 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9074 assert(ST->hasMVEIntegerOps() &&
9075 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9085 EVT SubVT = MVT::v4i32;
9087 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9097 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
9102 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9111 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9118 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9119 EVT VT =
N->getValueType(0);
9120 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9121 "Expected a vector i1 type!");
9123 EVT FromVT =
Op.getValueType();
9134 if (!Subtarget->hasMVEIntegerOps())
9137 EVT ToVT =
N->getValueType(0);
9180 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9182 EVT FromVT =
N->getOperand(0).getValueType();
9183 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9194 if (!Subtarget->hasMVEIntegerOps())
9199 EVT ToVT =
N->getValueType(0);
9200 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9203 EVT FromVT =
Op.getValueType();
9204 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9218 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9219 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9231 EVT VT =
N->getValueType(0);
9233 SDNode *BVN =
N->getOperand(0).getNode();
9238 unsigned HiElt = 1 - LoElt;
9243 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9259 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9260 SDNode *Elt =
N->getOperand(i).getNode();
9263 unsigned HalfSize = EltSize / 2;
9265 if (!
isIntN(HalfSize,
C->getSExtValue()))
9268 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9307 switch (OrigSimpleTy) {
9323 unsigned ExtOpcode) {
9346 if (ExtendedTy == LD->getMemoryVT())
9347 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9348 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9349 LD->getMemOperand()->getFlags());
9355 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9356 LD->getMemoryVT(), LD->getAlign(),
9357 LD->getMemOperand()->getFlags());
9370 N->getOperand(0)->getValueType(0),
9376 "Expected extending load");
9382 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9391 SDNode *BVN =
N->getOperand(0).getNode();
9393 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9401 EVT VT =
N->getValueType(0);
9407 for (
unsigned i = 0; i != NumElts; ++i) {
9408 const APInt &CInt =
N->getConstantOperandAPInt(i);
9417 unsigned Opcode =
N->getOpcode();
9419 SDNode *N0 =
N->getOperand(0).getNode();
9420 SDNode *N1 =
N->getOperand(1).getNode();
9428 unsigned Opcode =
N->getOpcode();
9430 SDNode *N0 =
N->getOperand(0).getNode();
9431 SDNode *N1 =
N->getOperand(1).getNode();
9441 EVT VT =
Op.getValueType();
9443 "unexpected type for custom-lowering ISD::MUL");
9444 SDNode *N0 =
Op.getOperand(0).getNode();
9445 SDNode *N1 =
Op.getOperand(1).getNode();
9446 unsigned NewOpc = 0;
9450 if (isN0SExt && isN1SExt)
9451 NewOpc = ARMISD::VMULLs;
9455 if (isN0ZExt && isN1ZExt)
9456 NewOpc = ARMISD::VMULLu;
9457 else if (isN1SExt || isN1ZExt) {
9461 NewOpc = ARMISD::VMULLs;
9464 NewOpc = ARMISD::VMULLu;
9468 NewOpc = ARMISD::VMULLu;
9474 if (VT == MVT::v2i64)
9491 "unexpected types for extended operands to VMULL");
9492 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9527 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9561 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9564 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9585 EVT VT =
Op.getValueType();
9586 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9587 "unexpected type for custom-lowering ISD::SDIV");
9594 if (VT == MVT::v8i8) {
9622 EVT VT =
Op.getValueType();
9623 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9624 "unexpected type for custom-lowering ISD::UDIV");
9631 if (VT == MVT::v8i8) {
9670 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9673 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9677 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9697 unsigned Opcode,
bool IsSigned) {
9698 EVT VT0 =
Op.getValue(0).getValueType();
9699 EVT VT1 =
Op.getValue(1).getValueType();
9701 bool InvertCarry = Opcode == ARMISD::SUBE;
9721 EVT VT =
Op.getValueType();
9722 assert((VT == MVT::i32 || VT == MVT::i64) &&
9723 "unexpected type for custom lowering DIV");
9729 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9731 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9738 for (
auto AI : {1, 0}) {
9740 Args.emplace_back(Operand,
9757ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9765 const bool MinSize =
ST.hasMinSize();
9766 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9767 :
ST.hasDivideInARMMode();
9771 if (
N->getOperand(0).getValueType().isVector())
9776 if (!(MinSize && HasDivide))
9789 if (Divisor.
sgt(128))
9797 assert(
Op.getValueType() == MVT::i32 &&
9798 "unexpected type for custom lowering DIV");
9801 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9804 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9810 if (
N->getValueType(0) == MVT::i32)
9811 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9814 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9818void ARMTargetLowering::ExpandDIV_Windows(
9823 assert(
Op.getValueType() == MVT::i64 &&
9824 "unexpected type for custom lowering DIV");
9839std::pair<SDValue, SDValue>
9840ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9846 EVT MemVT =
LD->getMemoryVT();
9847 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9851 unsigned AS =
LD->getAddressSpace();
9852 Align Alignment =
LD->getAlign();
9854 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9856 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9864 Opts, dl,
LD->getChain());
9889 EVT MemVT =
ST->getMemoryVT();
9890 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9894 unsigned AS =
ST->getAddressSpace();
9895 Align Alignment =
ST->getAlign();
9897 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9899 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9908 if (
ST->isTruncatingStore())
9913 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9914 dl,
ST->getChain());
9916 return CallResult.second;
9927 EVT MemVT = LD->getMemoryVT();
9928 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9929 MemVT == MVT::v16i1) &&
9930 "Expected a predicate type!");
9931 assert(MemVT ==
Op.getValueType());
9933 "Expected a non-extending load");
9934 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9948 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9950 LD->getMemOperand());
9956 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9957 if (MemVT != MVT::v16i1)
9966 EVT MemVT =
LD->getMemoryVT();
9968 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9969 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9970 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9971 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9974 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9975 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9980 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9981 auto Pair = LowerAEABIUnalignedLoad(
SDValue(
N, 0), DAG);
9983 Results.push_back(Pair.first);
9984 Results.push_back(Pair.second);
9991 EVT MemVT = ST->getMemoryVT();
9992 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9993 MemVT == MVT::v16i1) &&
9994 "Expected a predicate type!");
9995 assert(MemVT == ST->getValue().getValueType());
9996 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9997 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10002 SDValue Build = ST->getValue();
10003 if (MemVT != MVT::v16i1) {
10016 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
10022 ST->getChain(), dl, GRP, ST->getBasePtr(),
10024 ST->getMemOperand());
10030 EVT MemVT =
ST->getMemoryVT();
10032 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10033 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
10034 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10035 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10036 SDNode *
N =
Op.getNode();
10049 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10050 MemVT,
ST->getMemOperand());
10051 }
else if (Subtarget->hasMVEIntegerOps() &&
10052 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10053 MemVT == MVT::v16i1))) {
10055 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
10056 return LowerAEABIUnalignedStore(
Op, DAG);
10063 (
N->getOpcode() == ARMISD::VMOVIMM &&
10069 MVT VT =
Op.getSimpleValueType();
10071 SDValue PassThru =
N->getPassThru();
10082 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10083 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10084 N->getExtensionType(),
N->isExpandingLoad());
10087 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
10089 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10096 if (!ST->hasMVEIntegerOps())
10100 unsigned BaseOpcode = 0;
10101 switch (
Op->getOpcode()) {
10117 unsigned NumActiveLanes = NumElts;
10119 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10120 NumActiveLanes == 2) &&
10121 "Only expected a power 2 vector size");
10125 while (NumActiveLanes > 4) {
10126 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10128 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10129 NumActiveLanes /= 2;
10133 if (NumActiveLanes == 4) {
10143 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10144 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10145 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10151 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10155 if (EltVT !=
Op->getValueType(0))
10162 if (!ST->hasMVEFloatOps())
10169 if (!ST->hasNEON())
10177 unsigned PairwiseIntrinsic = 0;
10178 switch (
Op->getOpcode()) {
10182 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10185 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10188 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10191 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10197 unsigned NumActiveLanes = NumElts;
10199 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10200 NumActiveLanes == 2) &&
10201 "Only expected a power 2 vector size");
10207 VT =
Lo.getValueType();
10209 NumActiveLanes /= 2;
10213 while (NumActiveLanes > 1) {
10215 NumActiveLanes /= 2;
10222 if (EltVT !=
Op.getValueType()) {
10223 unsigned Extend = 0;
10224 switch (
Op->getOpcode()) {
10236 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10281 const SDValue Ops[] = {RegClass, V0, SubReg0,
V1, SubReg1};
10287 SDLoc dl(V.getNode());
10288 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10298 assert(
N->getValueType(0) == MVT::i64 &&
10299 "AtomicCmpSwap on types less than 64 should be legal");
10308 ARM::CMP_SWAP_64,
SDLoc(
N),
10309 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10328 EVT VT =
Op.getValueType();
10337 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10339 Chain, IsSignaling);
10340 if (!
RHS.getNode()) {
10356 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10358 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10359 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10376 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10379 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10392 if (!IsSigned && Subtarget->isThumb1Only()) {
10410 Sub1Result, Sub1Result, Flags1);
10425 if (
Op.getValueType() != MVT::i32)
10439 unsigned Opcode = ARMISD::SUBC;
10448 bool CanUseAdd =
false;
10464 Opcode = ARMISD::ADDC;
10488 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10489 GTCondValue, Flags);
10493 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10494 LTCondValue, Flags);
10496 if (
Op.getValueType() != MVT::i32)
10504 switch (
Op.getOpcode()) {
10536 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10540 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10541 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10563 return LowerSET_FPMODE(
Op, DAG);
10565 return LowerRESET_FPMODE(
Op, DAG);
10569 !
Op.getValueType().isVector())
10570 return LowerDIV_Windows(
Op, DAG,
true);
10574 !
Op.getValueType().isVector())
10575 return LowerDIV_Windows(
Op, DAG,
false);
10591 return LowerALUO(
Op, DAG);
10599 EVT MemVT = LD->getMemoryVT();
10600 if (Subtarget->hasMVEIntegerOps() &&
10601 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10602 MemVT == MVT::v16i1))
10605 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10611 return LowerSTORE(
Op, DAG, Subtarget);
10636 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10645 return LowerSPONENTRY(
Op, DAG);
10647 return LowerFP_TO_BF16(
Op, DAG);
10648 case ARMISD::WIN__DBZCHK:
return SDValue();
10651 return LowerCMP(
Op, DAG);
10653 return LowerABS(
Op, DAG);
10658 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10659 Op.getOperand(1).getValueType() == MVT::bf16) &&
10660 "Expected custom lowering of rounding operations only for f16");
10663 {
Op.getOperand(0),
Op.getOperand(1)});
10664 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10665 {Ext.getValue(1), Ext.getValue(0)});
10672 unsigned IntNo =
N->getConstantOperandVal(0);
10674 if (IntNo == Intrinsic::arm_smlald)
10675 Opc = ARMISD::SMLALD;
10676 else if (IntNo == Intrinsic::arm_smlaldx)
10677 Opc = ARMISD::SMLALDX;
10678 else if (IntNo == Intrinsic::arm_smlsld)
10679 Opc = ARMISD::SMLSLD;
10680 else if (IntNo == Intrinsic::arm_smlsldx)
10681 Opc = ARMISD::SMLSLDX;
10687 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10691 N->getOperand(1),
N->getOperand(2),
10703 switch (
N->getOpcode()) {
10710 Res = ExpandBITCAST(
N, DAG, Subtarget);
10719 Res = LowerREM(
N, DAG);
10723 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10740 "can only expand DIV on Windows");
10752 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10781 "ROPI/RWPI not currently supported with SjLj");
10790 bool isThumb = Subtarget->isThumb();
10791 bool isThumb2 = Subtarget->
isThumb2();
10794 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10800 : &ARM::GPRRegClass;
10906 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10909 MachineRegisterInfo *MRI = &MF->
getRegInfo();
10914 : &ARM::GPRnopcRegClass;
10918 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10919 unsigned MaxCSNum = 0;
10920 for (MachineBasicBlock &BB : *MF) {
10926 for (MachineInstr &
II : BB) {
10927 if (!
II.isEHLabel())
10930 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10931 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10933 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10934 for (
unsigned Idx : CallSiteIdxs) {
10935 CallSiteNumToLPad[Idx].push_back(&BB);
10936 MaxCSNum = std::max(MaxCSNum, Idx);
10943 std::vector<MachineBasicBlock*> LPadList;
10944 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10945 LPadList.reserve(CallSiteNumToLPad.
size());
10946 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10947 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10948 for (MachineBasicBlock *
MBB : MBBList) {
10949 LPadList.push_back(
MBB);
10954 assert(!LPadList.empty() &&
10955 "No landing pad destinations for the dispatch jump table!");
10958 MachineJumpTableInfo *JTI =
10965 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10968 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10970 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10973 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10977 MF->insert(MF->end(), DispatchBB);
10978 MF->insert(MF->end(), DispContBB);
10979 MF->insert(MF->end(), TrapBB);
10983 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10985 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10989 MachineInstrBuilder MIB;
10990 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10992 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
11002 unsigned NumLPads = LPadList.size();
11003 if (Subtarget->isThumb2()) {
11005 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11011 if (NumLPads < 256) {
11012 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11014 .
addImm(LPadList.size())
11018 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11019 .
addImm(NumLPads & 0xFFFF)
11022 unsigned VReg2 = VReg1;
11023 if ((NumLPads & 0xFFFF0000) != 0) {
11025 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11031 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11037 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11043 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11048 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11055 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11059 }
else if (Subtarget->isThumb()) {
11061 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11067 if (NumLPads < 256) {
11068 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11073 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11075 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11078 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11079 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11082 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11086 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11092 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11098 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11105 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11110 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11116 MachineMemOperand *JTMMOLd =
11121 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11127 unsigned NewVReg6 = NewVReg5;
11128 if (IsPositionIndependent) {
11130 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11137 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11142 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11148 if (NumLPads < 256) {
11149 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11153 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11155 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11156 .
addImm(NumLPads & 0xFFFF)
11159 unsigned VReg2 = VReg1;
11160 if ((NumLPads & 0xFFFF0000) != 0) {
11162 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11168 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11173 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11175 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11178 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11179 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11182 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11187 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11199 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11205 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11209 MachineMemOperand *JTMMOLd =
11213 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11220 if (IsPositionIndependent) {
11221 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11226 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11233 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11234 for (MachineBasicBlock *CurMBB : LPadList) {
11235 if (SeenMBBs.
insert(CurMBB).second)
11242 for (MachineBasicBlock *BB : InvokeBBs) {
11246 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11247 while (!Successors.empty()) {
11248 MachineBasicBlock *SMBB = Successors.pop_back_val();
11250 BB->removeSuccessor(SMBB);
11256 BB->normalizeSuccProbs();
11263 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11264 if (!
II->isCall())
continue;
11266 DenseSet<unsigned> DefRegs;
11268 OI =
II->operands_begin(), OE =
II->operands_end();
11270 if (!OI->isReg())
continue;
11271 DefRegs.
insert(OI->getReg());
11274 MachineInstrBuilder MIB(*MF, &*
II);
11276 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11277 unsigned Reg = SavedRegs[i];
11278 if (Subtarget->isThumb2() &&
11279 !ARM::tGPRRegClass.contains(
Reg) &&
11280 !ARM::hGPRRegClass.contains(
Reg))
11282 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11284 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11296 for (MachineBasicBlock *MBBLPad : MBBLPads)
11297 MBBLPad->setIsEHPad(
false);
11300 MI.eraseFromParent();
11313static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11315 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11316 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11318 return LdSize == 4 ? ARM::tLDRi
11319 : LdSize == 2 ? ARM::tLDRHi
11320 : LdSize == 1 ? ARM::tLDRBi : 0;
11322 return LdSize == 4 ? ARM::t2LDR_POST
11323 : LdSize == 2 ? ARM::t2LDRH_POST
11324 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11325 return LdSize == 4 ? ARM::LDR_POST_IMM
11326 : LdSize == 2 ? ARM::LDRH_POST
11327 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11332static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11334 return StSize == 16 ? ARM::VST1q32wb_fixed
11335 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11337 return StSize == 4 ? ARM::tSTRi
11338 : StSize == 2 ? ARM::tSTRHi
11339 : StSize == 1 ? ARM::tSTRBi : 0;
11341 return StSize == 4 ? ARM::t2STR_POST
11342 : StSize == 2 ? ARM::t2STRH_POST
11343 : StSize == 1 ? ARM::t2STRB_POST : 0;
11344 return StSize == 4 ? ARM::STR_POST_IMM
11345 : StSize == 2 ? ARM::STRH_POST
11346 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11353 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11354 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11355 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11356 assert(LdOpc != 0 &&
"Should have a load opcode");
11363 }
else if (IsThumb1) {
11369 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11374 }
else if (IsThumb2) {
11394 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11395 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11396 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11397 assert(StOpc != 0 &&
"Should have a store opcode");
11399 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11404 }
else if (IsThumb1) {
11411 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11416 }
else if (IsThumb2) {
11417 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11423 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11438 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11444 unsigned SizeVal =
MI.getOperand(2).getImm();
11445 unsigned Alignment =
MI.getOperand(3).getImm();
11449 MachineRegisterInfo &MRI = MF->
getRegInfo();
11450 unsigned UnitSize = 0;
11454 bool IsThumb1 = Subtarget->isThumb1Only();
11455 bool IsThumb2 = Subtarget->isThumb2();
11456 bool IsThumb = Subtarget->isThumb();
11458 if (Alignment & 1) {
11460 }
else if (Alignment & 2) {
11465 Subtarget->hasNEON()) {
11466 if ((Alignment % 16 == 0) && SizeVal >= 16)
11468 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11477 bool IsNeon = UnitSize >= 8;
11478 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11480 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11481 : UnitSize == 8 ? &ARM::DPRRegClass
11484 unsigned BytesLeft = SizeVal % UnitSize;
11485 unsigned LoopSize = SizeVal - BytesLeft;
11487 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11491 unsigned srcIn = src;
11492 unsigned destIn = dest;
11493 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11498 IsThumb1, IsThumb2);
11500 IsThumb1, IsThumb2);
11508 for (
unsigned i = 0; i < BytesLeft; i++) {
11513 IsThumb1, IsThumb2);
11515 IsThumb1, IsThumb2);
11519 MI.eraseFromParent();
11545 MF->
insert(It, loopMBB);
11546 MF->
insert(It, exitMBB);
11549 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11560 if (Subtarget->useMovt()) {
11561 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11564 }
else if (Subtarget->genExecuteOnly()) {
11565 assert(IsThumb &&
"Non-thumb expected to have used movt");
11570 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11574 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11575 MachineMemOperand *CPMMO =
11599 MachineBasicBlock *entryBB = BB;
11614 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11622 IsThumb1, IsThumb2);
11624 IsThumb1, IsThumb2);
11628 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11634 MachineInstrBuilder MIB =
11636 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11645 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11654 auto StartOfExit = exitMBB->
begin();
11658 unsigned srcIn = srcLoop;
11659 unsigned destIn = destLoop;
11660 for (
unsigned i = 0; i < BytesLeft; i++) {
11664 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11665 IsThumb1, IsThumb2);
11666 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11667 IsThumb1, IsThumb2);
11672 MI.eraseFromParent();
11680 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11683 assert(TM.getTargetTriple().isOSWindows() &&
11684 "__chkstk is only supported on Windows");
11685 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11705 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11706 if (ChkStkLibcall == RTLIB::Unsupported)
11710 switch (TM.getCodeModel()) {
11752 MI.eraseFromParent();
11761 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11776 .
addReg(
MI.getOperand(0).getReg())
11784 MI.eraseFromParent();
11808 if (miI == BB->
end()) {
11810 if (Succ->isLiveIn(ARM::CPSR))
11816 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11829 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11836 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11843 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11846 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11847 .
addUse(TotalIterationsReg)
11854 return TotalIterationsReg;
11865 Register TotalIterationsReg,
bool IsMemcpy) {
11874 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11884 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11892 Register RemainingLoopIterationsReg =
11894 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11895 .
addUse(TotalIterationsReg)
11897 .
addUse(RemainingLoopIterationsReg)
11903 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11904 .
addUse(ElementCountReg)
11906 .
addUse(RemainingElementsReg)
11911 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11912 .
addUse(PredCounterPhiReg)
11917 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11918 .
addUse(PredCounterPhiReg)
11927 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11936 SrcValueReg = OpSrcReg;
11938 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11949 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11950 .
addUse(LoopCounterPhiReg)
11953 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11954 .
addUse(RemainingLoopIterationsReg)
11972 "Invalid call instruction for a KCFI check");
11975 switch (
MBBI->getOpcode()) {
11978 case ARM::BLX_pred:
11979 case ARM::BLX_noip:
11980 case ARM::BLX_pred_noip:
11982 TargetOp = &
MBBI->getOperand(0);
11984 case ARM::TCRETURNri:
11985 case ARM::TCRETURNrinotr12:
11986 case ARM::TAILJMPr:
11987 case ARM::TAILJMPr4:
11988 TargetOp = &
MBBI->getOperand(0);
11994 case ARM::tBLXr_noip:
11995 case ARM::tBX_CALL:
11996 TargetOp = &
MBBI->getOperand(2);
11999 case ARM::tTAILJMPr:
12000 TargetOp = &
MBBI->getOperand(0);
12006 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
12010 unsigned KCFICheckOpcode;
12011 if (Subtarget->isThumb()) {
12012 if (Subtarget->isThumb2()) {
12013 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
12015 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
12018 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
12032 bool isThumb2 = Subtarget->isThumb2();
12033 switch (
MI.getOpcode()) {
12040 case ARM::tLDR_postidx: {
12044 .
add(
MI.getOperand(2))
12045 .
add(
MI.getOperand(3))
12046 .
add(
MI.getOperand(4))
12047 .
add(
MI.getOperand(0))
12049 MI.eraseFromParent();
12053 case ARM::MVE_MEMCPYLOOPINST:
12054 case ARM::MVE_MEMSETLOOPINST: {
12084 Register OpDestReg =
MI.getOperand(0).getReg();
12085 Register OpSrcReg =
MI.getOperand(1).getReg();
12086 Register OpSizeReg =
MI.getOperand(2).getReg();
12106 if (TpExit == BB) {
12108 "block containing memcpy/memset Pseudo");
12118 genTPEntry(TpEntry, TpLoopBody, TpExit, OpSizeReg,
TII, dl, MRI);
12121 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12123 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12126 Properties.resetNoPHIs();
12138 MI.eraseFromParent();
12148 case ARM::t2STR_preidx:
12149 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12151 case ARM::t2STRB_preidx:
12152 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12154 case ARM::t2STRH_preidx:
12155 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12158 case ARM::STRi_preidx:
12159 case ARM::STRBi_preidx: {
12160 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12161 : ARM::STRB_PRE_IMM;
12163 unsigned Offset =
MI.getOperand(4).getImm();
12171 .
add(
MI.getOperand(0))
12172 .
add(
MI.getOperand(1))
12173 .
add(
MI.getOperand(2))
12175 .
add(
MI.getOperand(5))
12176 .
add(
MI.getOperand(6))
12178 MI.eraseFromParent();
12181 case ARM::STRr_preidx:
12182 case ARM::STRBr_preidx:
12183 case ARM::STRH_preidx: {
12185 switch (
MI.getOpcode()) {
12187 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12188 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12189 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12194 MI.eraseFromParent();
12198 case ARM::tMOVCCr_pseudo: {
12216 F->insert(It, copy0MBB);
12217 F->insert(It, sinkMBB);
12220 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12226 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12242 .
addImm(
MI.getOperand(3).getImm())
12243 .
addReg(
MI.getOperand(4).getReg());
12258 .
addReg(
MI.getOperand(1).getReg())
12260 .
addReg(
MI.getOperand(2).getReg())
12263 MI.eraseFromParent();
12268 case ARM::BCCZi64: {
12274 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12279 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12283 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12289 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12293 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12303 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12312 MI.eraseFromParent();
12316 case ARM::Int_eh_sjlj_setjmp:
12317 case ARM::Int_eh_sjlj_setjmp_nofp:
12318 case ARM::tInt_eh_sjlj_setjmp:
12319 case ARM::t2Int_eh_sjlj_setjmp:
12320 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12323 case ARM::Int_eh_sjlj_setup_dispatch:
12324 EmitSjLjDispatchBlock(
MI, BB);
12326 case ARM::COPY_STRUCT_BYVAL_I32:
12328 return EmitStructByval(
MI, BB);
12329 case ARM::WIN__CHKSTK:
12330 return EmitLowered__chkstk(
MI, BB);
12331 case ARM::WIN__DBZCHK:
12332 return EmitLowered__dbzchk(
MI, BB);
12348 if (!
Node->hasAnyUseOfValue(0)) {
12349 MI.getOperand(0).setIsDead(
true);
12351 if (!
Node->hasAnyUseOfValue(1)) {
12352 MI.getOperand(1).setIsDead(
true);
12356 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12358 : &ARM::GPRRegClass);
12365 if (
MI.getOpcode() == ARM::MEMCPY) {
12386 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12387 &&
"converted opcode should be the same except for cc_out"
12388 " (and, on Thumb1, pred)");
12396 if (Subtarget->isThumb1Only()) {
12397 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12398 MI.addOperand(
MI.getOperand(1));
12399 MI.removeOperand(1);
12403 for (
unsigned i =
MI.getNumOperands(); i--;) {
12405 if (
op.isReg() &&
op.isUse()) {
12408 MI.tieOperands(DefIdx, i);
12416 ccOutIdx =
MCID->getNumOperands() - 1;
12418 ccOutIdx =
MCID->getNumOperands() - 1;
12422 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12423 assert(!NewOpc &&
"Optional cc_out operand required");
12428 bool definesCPSR =
false;
12429 bool deadCPSR =
false;
12430 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12434 definesCPSR =
true;
12437 MI.removeOperand(i);
12441 if (!definesCPSR) {
12442 assert(!NewOpc &&
"Optional cc_out operand required");
12445 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12447 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12448 "expect uninitialized optional cc_out operand");
12450 if (!Subtarget->isThumb1Only())
12486 switch (
N->getOpcode()) {
12487 default:
return false;
12489 CC =
N->getOperand(0);
12511 EVT VT =
N->getValueType(0);
12512 CC =
N->getOperand(0);
12559 EVT VT =
N->getValueType(0);
12562 bool SwapSelectOps;
12564 NonConstantVal, DAG))
12570 OtherOp, NonConstantVal);
12576 CCOp, TrueVal, FalseVal);
12596 if (
N->getOpcode() == ARMISD::VUZP)
12600 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12615 if (!
N->getValueType(0).is64BitVector())
12623 EVT VT =
N->getValueType(0);
12662 EVT VT =
N->getValueType(0);
12668 Opcode = Intrinsic::arm_neon_vpaddls;
12670 Opcode = Intrinsic::arm_neon_vpaddlu;
12698 EVT VT =
N->getValueType(0);
12713 unsigned nextIndex = 0;
12764 Ops.push_back(Vec);
12781 return DAG.
getNode(ExtOp, dl, VT, tmp);
12812 if (SRA.getOpcode() !=
ISD::SRA) {
12819 if (Const->getZExtValue() != 31)
12824 if (SRA.getOperand(0) !=
Mul)
12828 SDLoc dl(AddcNode);
12829 unsigned Opcode = 0;
12834 Opcode = ARMISD::SMLALBB;
12835 Op0 =
Mul.getOperand(0);
12836 Op1 =
Mul.getOperand(1);
12838 Opcode = ARMISD::SMLALBT;
12839 Op0 =
Mul.getOperand(0);
12840 Op1 =
Mul.getOperand(1).getOperand(0);
12842 Opcode = ARMISD::SMLALTB;
12843 Op0 =
Mul.getOperand(0).getOperand(0);
12844 Op1 =
Mul.getOperand(1);
12846 Opcode = ARMISD::SMLALTT;
12847 Op0 =
Mul->getOperand(0).getOperand(0);
12848 Op1 =
Mul->getOperand(1).getOperand(0);
12864 SDValue resNode(AddcNode, 0);
12892 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12893 "Expect an ADDE or SUBE");
12897 "ADDE node has the wrong inputs");
12901 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12902 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12903 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12904 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12916 "Expect ADDC with two result values. First: i32");
12920 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12936 bool IsLeftOperandMUL =
false;
12941 IsLeftOperandMUL =
true;
12952 SDValue *LowAddSub =
nullptr;
12955 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12958 if (IsLeftOperandMUL)
12959 HiAddSub = &AddeSubeOp1;
12961 HiAddSub = &AddeSubeOp0;
12966 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12967 LoMul = &AddcSubcOp0;
12968 LowAddSub = &AddcSubcOp1;
12970 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12971 LoMul = &AddcSubcOp1;
12972 LowAddSub = &AddcSubcOp0;
12980 if (AddcSubcNode == HiAddSub->getNode() ||
12996 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13001 Ops.push_back(*HiAddSub);
13002 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
13003 FinalOpc = ARMISD::SMMLSR;
13005 FinalOpc = ARMISD::SMMLAR;
13010 return SDValue(AddeSubeNode, 0);
13011 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
13017 Ops.push_back(*LowAddSub);
13018 Ops.push_back(*HiAddSub);
13031 return SDValue(AddeSubeNode, 0);
13043 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13048 if (AddcNode->
getOpcode() != ARMISD::ADDC)
13052 SDNode *UmlalNode =
nullptr;
13091 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13096 SDNode* AddcNode =
N->getOperand(2).getNode();
13097 SDNode* AddeNode =
N->getOperand(3).getNode();
13098 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
13099 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
13105 {N->getOperand(0), N->getOperand(1),
13106 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13116 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13120 if (
LHS->getOpcode() == ARMISD::ADDE &&
13130 int32_t imm =
C->getSExtValue();
13131 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13134 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13136 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13151 int64_t imm =
C->getSExtValue();
13160 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13162 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13163 N->getOperand(0),
RHS,
N->getOperand(2));
13175 if (!Subtarget->hasMVEIntegerOps())
13188 SetCC =
N->getOperand(0);
13192 TrueVal =
N->getOperand(1);
13193 FalseVal =
N->getOperand(2);
13195 LHS =
N->getOperand(0);
13196 RHS =
N->getOperand(1);
13198 TrueVal =
N->getOperand(2);
13199 FalseVal =
N->getOperand(3);
13204 unsigned int Opcode = 0;
13208 Opcode = ARMISD::VMINVu;
13214 Opcode = ARMISD::VMINVs;
13220 Opcode = ARMISD::VMAXVu;
13226 Opcode = ARMISD::VMAXVs;
13233 switch (TrueVal->getOpcode()) {
13252 if (TrueVal !=
LHS || FalseVal !=
RHS)
13255 EVT LeftType =
LHS->getValueType(0);
13256 EVT RightType =
RHS->getValueType(0);
13259 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13263 if (VectorScalarType != MVT::i32)
13271 if (VectorScalarType != MVT::i32)
13284 EVT VT =
N->getValueType(0);
13292 Shft =
N->getOperand(0);
13299 Cmp.getOperand(0) !=
N->getOperand(1) ||
13300 Cmp.getOperand(1) !=
N->getOperand(2))
13302 Shft =
N->getOperand(1);
13314 ScalarType = MVT::i8;
13317 case (1 << 15) - 1:
13318 ScalarType = MVT::i16;
13321 case (1ULL << 31) - 1:
13322 ScalarType = MVT::i32;
13353 unsigned LegalLanes = 128 / (ShftAmt + 1);
13365 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13366 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13367 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13368 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13377 for (
unsigned I = 0;
I < NumParts; ++
I) {
13384 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13394 if (!Subtarget->hasMVEIntegerOps())
13399 if (
N->getOperand(0).getOpcode() == ARMISD::PREDICATE_CAST &&
13401 unsigned C =
N->getOperand(0).getConstantOperandVal(0);
13403 return N->getOperand(2);
13405 return N->getOperand(1);
13420 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13430 if (!Const || !Const->isOne())
13448 EVT VT =
N->getValueType(0);
13450 if (!Subtarget->hasMVEIntegerOps() ||
13479 Opc = Intrinsic::arm_mve_vctp64;
13482 Opc = Intrinsic::arm_mve_vctp32;
13485 Opc = Intrinsic::arm_mve_vctp16;
13488 Opc = Intrinsic::arm_mve_vctp8;
13542 EVT VT =
N->getValueType(0);
13548 switch (
Op.getOpcode()) {
13550 case ARMISD::VADDVs:
13551 case ARMISD::VADDVu:
13552 case ARMISD::VMLAVs:
13553 case ARMISD::VMLAVu:
13573 unsigned N0RedOp = 0;
13580 unsigned N1RedOp = 0;
13594 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13596 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13603 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13627 if (!BaseLocDecomp0.getBase() ||
13628 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13629 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13631 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13633 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13643 if (IsBefore < 0) {
13646 }
else if (IsBefore > 0) {
13659 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13669 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13679 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13681 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13688 if (!Subtarget->hasMVEIntegerOps())
13694 EVT VT =
N->getValueType(0);
13699 if (VT != MVT::i64)
13710 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13730 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13739 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13741 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13743 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13745 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13747 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13749 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13751 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13753 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13755 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13757 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13759 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13761 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13763 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13765 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13767 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13769 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13779 "Expected shift op");
13781 SDValue ShiftLHS =
N->getOperand(0);
13795 if (Subtarget->isThumb1Only()) {
13806 if (Const->getAPIntValue().ult(256))
13809 Const->getAPIntValue().sgt(-256))
13825 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13826 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13827 "Expected XOR(SHIFT) pattern");
13832 if (XorC && ShiftC) {
13833 unsigned MaskIdx, MaskLen;
13834 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13835 unsigned ShiftAmt = ShiftC->getZExtValue();
13836 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13837 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13838 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13839 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13849 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13851 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13852 "Expected shift-shift mask");
13854 if (!Subtarget->isThumb1Only())
13857 EVT VT =
N->getValueType(0);
13865 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13867 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13872 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps()) {
13873 if (Subtarget->isThumb1Only())
13887 return Subtarget->hasVFP2Base();
13889 return Subtarget->hasVFP2Base();
13891 return Subtarget->hasFP64();
13894 return Subtarget->hasMVEFloatOps();
13923 if (ST->isThumb1Only())
13927 for (
auto *U :
N->users()) {
13928 switch(U->getOpcode()) {
13946 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13947 U->getOperand(1).getOpcode() ==
ISD::SHL)
13957 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13964 if (!C1ShlC2 || !C2)
13967 APInt C2Int = C2->getAPIntValue();
13968 APInt C1Int = C1ShlC2->getAPIntValue();
13970 if (C2Int.
uge(C2Width))
13976 if ((C1Int & Mask) != C1Int)
13983 auto LargeImm = [](
const APInt &Imm) {
13984 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13985 return Imm.getBitWidth() - Zeros > 8;
13988 if (LargeImm(C1Int) || LargeImm(C2Int))
14000 SHL.dump();
N->dump());
14061 if (
Op.hasOneUse() && ShiftAmt &&
14062 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
14120 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14141 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14162 if (!Subtarget->hasVMLxForwarding())
14181 EVT VT =
N->getValueType(0);
14192 EVT VT =
N->getValueType(0);
14193 if (VT != MVT::v2i64)
14204 return Op->getOperand(0);
14218 And =
And->getOperand(0);
14223 Mask = Mask->getOperand(0);
14226 Mask.getValueType() != MVT::v4i32)
14232 return And->getOperand(0);
14237 if (
SDValue Op0 = IsSignExt(N0)) {
14238 if (
SDValue Op1 = IsSignExt(N1)) {
14239 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14240 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14241 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14244 if (
SDValue Op0 = IsZeroExt(N0)) {
14245 if (
SDValue Op1 = IsZeroExt(N1)) {
14246 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14247 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14248 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14260 EVT VT =
N->getValueType(0);
14261 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14272 if (VT != MVT::i32)
14279 int64_t MulAmt =
C->getSExtValue();
14282 ShiftAmt = ShiftAmt & (32 - 1);
14287 MulAmt >>= ShiftAmt;
14348 if (
N->getValueType(0) != MVT::i32)
14357 if (C1 == 255 || C1 == 65535)
14360 SDNode *N0 =
N->getOperand(0).getNode();
14374 if (!C2 || C2 >= 32)
14418 if (Trailing == C2 && C2 + C3 < 32) {
14431 if (Leading == C2 && C2 + C3 < 32) {
14459 EVT VT =
N->getValueType(0);
14463 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14466 APInt SplatBits, SplatUndef;
14467 unsigned SplatBitSize;
14469 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14470 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14471 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14472 SplatBitSize == 64) {
14479 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14481 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14506 if (!Subtarget->hasV6Ops() ||
14507 (Subtarget->isThumb() &&
14508 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14511 SDValue SRL = OR->getOperand(0);
14512 SDValue SHL = OR->getOperand(1);
14515 SRL = OR->getOperand(1);
14516 SHL = OR->getOperand(0);
14523 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14527 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14528 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14529 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14548 unsigned Opcode = 0;
14549 if (
isS16(OpS16, DAG))
14550 Opcode = ARMISD::SMULWB;
14552 Opcode = ARMISD::SMULWT;
14567 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14570 EVT VT =
N->getValueType(0);
14585 if (VT != MVT::i32)
14598 if (Mask == 0xffff)
14605 if ((Val & ~Mask) != Val)
14611 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14630 (Mask == ~Mask2)) {
14633 if (Subtarget->hasDSP() &&
14634 (Mask == 0xffff || Mask == 0xffff0000))
14640 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14647 (~Mask == Mask2)) {
14650 if (Subtarget->hasDSP() &&
14651 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14707 if (
N->getOpcode() == ARMISD::VCMP)
14709 else if (
N->getOpcode() == ARMISD::VCMPZ)
14717 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14724 EVT VT =
N->getValueType(0);
14729 auto IsFreelyInvertable = [&](
SDValue V) {
14730 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14736 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14754 if (AndOp.getOpcode() !=
ISD::AND)
14758 SDValue Mask = AndOp.getOperand(1);
14768 bool IsShiftRight =
false;
14771 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14772 IsShiftRight =
true;
14775 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14783 APInt RequiredMask = IsShiftRight
14786 if (MaskBits != RequiredMask)
14789 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14799 EVT VT =
N->getValueType(0);
14805 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14806 VT == MVT::v8i1 || VT == MVT::v16i1))
14809 APInt SplatBits, SplatUndef;
14810 unsigned SplatBitSize;
14812 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14813 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14814 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14815 SplatBitSize == 64) {
14822 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14824 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14844 (Subtarget->hasMVEIntegerOps() &&
14845 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14848 return ShiftInsert;
14852 return ShiftInsert;
14866 unsigned SplatBitSize;
14869 APInt SplatBits0, SplatBits1;
14873 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14874 HasAnyUndefs) && !HasAnyUndefs) {
14875 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14876 HasAnyUndefs) && !HasAnyUndefs) {
14881 SplatBits0 == ~SplatBits1) {
14889 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14909 if (CSINC.
getOpcode() != ARMISD::CSINC)
14911 if (CSINC.
getOpcode() == ARMISD::CSINC &&
14924 EVT VT =
N->getValueType(0);
14939 if (Subtarget->hasMVEIntegerOps()) {
14967 assert(
N->getOpcode() == ARMISD::BFI);
14970 ToMask =
~N->getConstantOperandAPInt(2);
14990 unsigned LastActiveBitInA =
A.countr_zero();
14991 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14992 return LastActiveBitInA - 1 == FirstActiveBitInB;
14997 APInt ToMask, FromMask;
15002 if (V.getOpcode() != ARMISD::BFI)
15005 APInt NewToMask, NewFromMask;
15007 if (NewFrom != From)
15011 if ((NewToMask & ToMask).getBoolValue())
15036 unsigned InvMask =
N->getConstantOperandVal(2);
15040 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
15041 "undefined behavior");
15042 unsigned Mask = (1u << Width) - 1;
15044 if ((Mask & (~Mask2)) == 0)
15046 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
15053 APInt ToMask1, FromMask1;
15056 APInt ToMask2, FromMask2;
15062 APInt NewFromMask = FromMask1 | FromMask2;
15063 APInt NewToMask = ToMask1 | ToMask2;
15065 EVT VT =
N->getValueType(0);
15068 if (NewFromMask[0] == 0)
15071 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
15079 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
15080 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
15081 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
15083 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
15087 EVT VT =
N->getValueType(0);
15090 N->getOperand(1),
N->getOperand(2));
15102 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
15104 SDValue CSInc = Cmp->getOperand(0);
15114 if (CSInc.
getOpcode() == ARMISD::CSINC &&
15154 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15155 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15158 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15160 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15173 SDValue InDouble =
N->getOperand(0);
15174 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15188 SDValue BasePtr = LD->getBasePtr();
15190 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15191 LD->getAlign(), LD->getMemOperand()->getFlags());
15197 LD->getPointerInfo().getWithOffset(4),
15199 LD->getMemOperand()->getFlags());
15218 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15232 if (!Subtarget->
isLittle() && BVSwap)
15250 if (!Subtarget->
isLittle() && BVSwap)
15269 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15282 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15295 if (Copy.getValueType() == MVT::f32 &&
15297 bool HasGlue = Copy->getNumOperands() == 3;
15298 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15299 HasGlue ? Copy->getOperand(2) :
SDValue()};
15300 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15319 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15320 LN0->getMemoryVT() == MVT::i16) {
15323 LN0->getBasePtr(), LN0->getMemOperand());
15341 EVT VT =
N->getValueType(0);
15375 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15376 for (
unsigned i = 0; i < NumElts; ++i) {
15377 SDNode *Elt =
N->getOperand(i).getNode();
15394 if (
N->getNumOperands() == 2)
15400 EVT VT =
N->getValueType(0);
15406 for (
unsigned i = 0; i < NumElts; ++i) {
15432 EVT VT =
N->getValueType(0);
15440 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15445 Use->getValueType(0).isFloatingPoint())
15453 unsigned NumOfBitCastedElts = 0;
15455 unsigned NumOfRelevantElts = NumElts;
15456 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15461 ++NumOfBitCastedElts;
15465 --NumOfRelevantElts;
15469 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15487 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15492 V->getOperand(0).getValueType() == MVT::i32)
15494 V = V.getOperand(0);
15511 EVT VT =
N->getValueType(0);
15516 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15518 if (
Op->getOperand(0).getValueType() == VT)
15519 return Op->getOperand(0);
15520 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15527 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15534 if (
Op.getValueType() == MVT::i32) {
15545 EVT VT =
N->getValueType(0);
15550 if (ST->isLittle())
15554 if (
Op.getValueType() == VT)
15561 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15563 if (
Op->getOperand(0).getValueType() == VT)
15564 return Op->getOperand(0);
15565 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15573 if (!Subtarget->hasMVEIntegerOps())
15576 EVT VT =
N->getValueType(0);
15584 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15590 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15594 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15607 EVT VT =
N->getValueType(0);
15608 SDNode *Elt =
N->getOperand(1).getNode();
15623 Vec, V,
N->getOperand(2));
15633 EVT VT =
N->getValueType(0);
15661 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15662 isa<ConstantSDNode>(V->getOperand(1)) &&
15663 V->getConstantOperandVal(1) == Lane + 1 &&
15664 V->getOperand(0).getResNo() == ResNo;
15666 if (OtherIt == Op0->
users().
end())
15671 SDValue OtherExt(*OtherIt, 0);
15683 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15686 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15696 EVT VT =
N->getValueType(0);
15700 if (Op0->
getOpcode() == ARMISD::VDUP) {
15702 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15703 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15704 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15705 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15706 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15709 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15710 X =
X->getOperand(0);
15711 if (
X.getValueType() == VT)
15719 return Op0.
getOperand(
N->getConstantOperandVal(1));
15729 unsigned Offset =
N->getConstantOperandVal(1);
15731 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15741 unsigned Idx =
N->getConstantOperandVal(1);
15756 unsigned Lane =
N->getConstantOperandVal(1);
15784 EVT VT =
N->getValueType(0);
15787 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15789 Op.getOperand(0).getValueType().getScalarType())
15790 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15799 SDValue SubVec =
N->getOperand(1);
15800 uint64_t IdxVal =
N->getConstantOperandVal(2);
15811 if (IdxVal == 0 && Vec.
isUndef())
15817 (IdxVal != 0 && IdxVal != NumSubElts))
15848 ARMISD::VMOVN,
DL, VT,
15854 ARMISD::VMOVN,
DL, VT,
15890 EVT VT =
N->getValueType(0);
15901 unsigned HalfElts = NumElts/2;
15903 for (
unsigned n = 0; n < NumElts; ++n) {
15906 if (MaskElt < (
int)HalfElts)
15908 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15909 NewElt = HalfElts + MaskElt - NumElts;
15952 bool SimpleConstIncOnly,
15960 bool isLoadOp =
true;
15961 bool isLaneOp =
false;
15964 bool hasAlignment =
true;
15965 unsigned NewOpc = 0;
15966 unsigned NumVecs = 0;
15967 if (
Target.isIntrinsic) {
15968 unsigned IntNo =
N->getConstantOperandVal(1);
15972 case Intrinsic::arm_neon_vld1:
15976 case Intrinsic::arm_neon_vld2:
15980 case Intrinsic::arm_neon_vld3:
15984 case Intrinsic::arm_neon_vld4:
15988 case Intrinsic::arm_neon_vld1x2:
15991 hasAlignment =
false;
15993 case Intrinsic::arm_neon_vld1x3:
15996 hasAlignment =
false;
15998 case Intrinsic::arm_neon_vld1x4:
16001 hasAlignment =
false;
16003 case Intrinsic::arm_neon_vld2dup:
16007 case Intrinsic::arm_neon_vld3dup:
16011 case Intrinsic::arm_neon_vld4dup:
16015 case Intrinsic::arm_neon_vld2lane:
16020 case Intrinsic::arm_neon_vld3lane:
16025 case Intrinsic::arm_neon_vld4lane:
16030 case Intrinsic::arm_neon_vst1:
16035 case Intrinsic::arm_neon_vst2:
16036 NewOpc = ARMISD::VST2_UPD;
16040 case Intrinsic::arm_neon_vst3:
16045 case Intrinsic::arm_neon_vst4:
16046 NewOpc = ARMISD::VST4_UPD;
16050 case Intrinsic::arm_neon_vst2lane:
16056 case Intrinsic::arm_neon_vst3lane:
16062 case Intrinsic::arm_neon_vst4lane:
16068 case Intrinsic::arm_neon_vst1x2:
16072 hasAlignment =
false;
16074 case Intrinsic::arm_neon_vst1x3:
16078 hasAlignment =
false;
16080 case Intrinsic::arm_neon_vst1x4:
16084 hasAlignment =
false;
16089 switch (
N->getOpcode()) {
16125 VecTy =
N->getValueType(0);
16126 }
else if (
Target.isIntrinsic) {
16127 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16130 "Node has to be a load, a store, or an intrinsic!");
16131 VecTy =
N->getOperand(1).getValueType();
16139 if (isLaneOp || isVLDDUPOp)
16142 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16148 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16157 EVT AlignedVecTy = VecTy;
16177 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16178 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16189 Alignment =
Align(1);
16195 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16197 for (n = 0; n < NumResultVecs; ++n)
16198 Tys[n] = AlignedVecTy;
16199 Tys[n++] = MVT::i32;
16200 Tys[n] = MVT::Other;
16205 Ops.push_back(
N->getOperand(0));
16206 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16211 Ops.push_back(StN->getValue());
16215 unsigned LastOperand =
16216 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16217 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16218 Ops.push_back(
N->getOperand(i));
16226 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16237 for (
unsigned i = 0; i < NumResultVecs; ++i)
16242 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16243 SDValue &LdVal = NewResults[0];
16279 switch (
N->getOpcode()) {
16283 *Ptr =
N->getOperand(0);
16284 *CInc =
N->getOperand(1);
16291 *Ptr =
N->getOperand(1);
16292 *CInc =
N->getOperand(2);
16319 SDValue Addr =
N->getOperand(AddrOpIdx);
16330 unsigned ConstInc =
16335 if (BaseUpdates.
size() >= MaxBaseUpdates)
16356 unsigned UserOffset =
16359 if (!UserOffset || UserOffset <=
Offset)
16362 unsigned NewConstInc = UserOffset -
Offset;
16365 if (BaseUpdates.
size() >= MaxBaseUpdates)
16373 unsigned NumValidUpd = BaseUpdates.
size();
16374 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16385 return LHS.ConstInc <
RHS.ConstInc;
16414 unsigned IntNo =
N->getConstantOperandVal(1);
16415 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16417 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16440 bool isLoadOp =
true;
16441 unsigned NewOpc = 0;
16442 unsigned NumVecs = 0;
16446 case Intrinsic::arm_mve_vld2q:
16450 case Intrinsic::arm_mve_vld4q:
16454 case Intrinsic::arm_mve_vst2q:
16455 NewOpc = ARMISD::VST2_UPD;
16459 case Intrinsic::arm_mve_vst4q:
16460 NewOpc = ARMISD::VST4_UPD;
16469 VecTy =
N->getValueType(0);
16471 VecTy =
N->getOperand(3).getValueType();
16485 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16487 for (n = 0; n < NumResultVecs; ++n)
16489 Tys[n++] = MVT::i32;
16490 Tys[n] = MVT::Other;
16495 Ops.push_back(
N->getOperand(0));
16496 Ops.push_back(
N->getOperand(2));
16497 Ops.push_back(Inc);
16499 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16500 Ops.push_back(
N->getOperand(i));
16507 for (
unsigned i = 0; i < NumResultVecs; ++i)
16526 EVT VT =
N->getValueType(0);
16532 SDNode *VLD =
N->getOperand(0).getNode();
16535 unsigned NumVecs = 0;
16536 unsigned NewOpc = 0;
16538 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16541 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16544 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16556 if (
Use.getResNo() == NumVecs)
16559 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16560 VLDLaneNo !=
User->getConstantOperandVal(1))
16567 for (n = 0; n < NumVecs; ++n)
16569 Tys[n] = MVT::Other;
16579 unsigned ResNo =
Use.getResNo();
16581 if (ResNo == NumVecs)
16588 std::vector<SDValue> VLDDupResults;
16589 for (
unsigned n = 0; n < NumVecs; ++n)
16603 EVT VT =
N->getValueType(0);
16606 if (Subtarget->hasMVEIntegerOps()) {
16610 ExtractVT = MVT::i32;
16612 N->getOperand(0),
N->getOperand(1));
16624 Op =
Op.getOperand(0);
16625 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16629 unsigned EltSize =
Op.getScalarValueSizeInBits();
16631 unsigned Imm =
Op.getConstantOperandVal(0);
16647 if (Subtarget->hasMVEIntegerOps()) {
16650 if (
Op.getValueType() == MVT::f32)
16651 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16653 else if (
Op.getValueType() == MVT::f16)
16654 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16655 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16658 if (!Subtarget->hasNEON())
16665 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16666 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16667 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16672 LD->getMemoryVT(), LD->getMemOperand());
16683 EVT VT =
N->getValueType(0);
16705 assert(StVT != VT &&
"Cannot truncate to the same type");
16715 if (0 != (NumElems * FromEltSz) % ToEltSz)
16718 unsigned SizeRatio = FromEltSz / ToEltSz;
16723 NumElems * SizeRatio);
16729 for (
unsigned i = 0; i < NumElems; ++i)
16743 MVT StoreType = MVT::i8;
16745 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16765 for (
unsigned I = 0;
I <
E;
I++) {
16796 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16799 unsigned NumElements = 4;
16816 unsigned Off0 = Rev ? NumElts : 0;
16817 unsigned Off1 = Rev ? 0 : NumElts;
16819 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16820 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16822 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16830 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16850 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16861 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16865 NewToVT, Alignment, MMOFlags, AAInfo);
16898 unsigned NewOffset =
16906 NewToVT, Alignment, MMOFlags, AAInfo);
16928 {Extract.getOperand(0), Extract.getOperand(1)});
16959 if (Subtarget->hasNEON())
16963 if (Subtarget->hasMVEFloatOps())
16967 if (Subtarget->hasMVEIntegerOps()) {
17041 if (!Subtarget->hasNEON())
17045 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
17053 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
17055 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
17056 uint32_t IntBits = IntTy.getSizeInBits();
17057 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17058 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17069 if (
C == -1 ||
C == 0 ||
C > 32)
17074 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
17075 Intrinsic::arm_neon_vcvtfp2fxu;
17078 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
17081 if (IntBits < FloatBits)
17089 if (!Subtarget->hasMVEFloatOps())
17097 EVT VT =
N->getValueType(0);
17102 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
17104 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
17106 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
17107 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
17109 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17122 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17133 EVT VT =
N->getValueType(0);
17136 if (!
N->getFlags().hasAllowReassociation())
17143 unsigned Opc =
A.getConstantOperandVal(0);
17144 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17149 A.getOperand(3),
A.getOperand(4));
17181 if (!Subtarget->hasNEON())
17185 unsigned OpOpcode =
Op.getNode()->getOpcode();
17186 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17190 SDValue ConstVec =
N->getOperand(1);
17194 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17196 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17197 uint32_t IntBits = IntTy.getSizeInBits();
17198 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17199 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17219 int32_t
C = IntVal.exactLogBase2();
17220 if (
C == -1 ||
C == 0 ||
C > 32)
17226 if (IntBits < FloatBits)
17228 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17230 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17231 : Intrinsic::arm_neon_vcvtfxu2fp;
17239 if (!ST->hasMVEIntegerOps())
17243 EVT ResVT =
N->getValueType(0);
17271 EVT AVT =
A.getValueType();
17277 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17278 EVT AVT =
A.getValueType();
17288 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17289 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17292 if (ExtTypeMatches(
A, ExtTypes))
17293 return ExtendIfNeeded(
A, ExtendCode);
17296 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17306 if (ExtTypeMatches(
A, ExtTypes))
17307 return ExtendIfNeeded(
A, ExtendCode);
17310 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17320 if (ResVT != RetTy)
17323 if (
Mul->getOpcode() == ExtendCode &&
17324 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17326 Mul =
Mul->getOperand(0);
17335 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17336 A = ExtendIfNeeded(
A, ExtendCode);
17337 B = ExtendIfNeeded(
B, ExtendCode);
17342 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17355 if (
Mul->getOpcode() == ExtendCode &&
17356 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17358 Mul =
Mul->getOperand(0);
17367 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17368 A = ExtendIfNeeded(
A, ExtendCode);
17369 B = ExtendIfNeeded(
B, ExtendCode);
17380 EVT VT =
Ops[0].getValueType();
17381 if (VT == MVT::v16i8) {
17382 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17383 "Unexpected illegal long reduction opcode");
17384 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17396 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17409 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17411 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17412 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17414 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17415 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17417 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17420 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17423 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17427 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17430 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17433 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17436 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17439 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17442 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17445 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17447 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17449 return Create64bitNode(ARMISD::VADDLVs, {
A});
17451 return Create64bitNode(ARMISD::VADDLVu, {
A});
17454 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17457 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17460 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17462 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17464 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17466 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17469 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17472 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17479 Op =
Op->getOperand(1);
17481 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17483 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17500 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17502 if (!Shuf || !Shuf->getOperand(1).isUndef())
17507 APInt SetElts(Mask.size(), 0);
17508 for (
int E : Mask) {
17516 if (
N->getNumOperands() != VecOp + 1) {
17518 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17524 if (
Op.getValueType().isVector())
17525 Ops.push_back(
Op.getOperand(0));
17536 unsigned IsTop =
N->getConstantOperandVal(2);
17543 if (Op0->
isUndef() && !IsTop)
17548 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17549 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17557 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17559 APInt Op0DemandedElts =
17560 IsTop ? Op1DemandedElts
17575 unsigned IsTop =
N->getConstantOperandVal(2);
17577 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17578 APInt Op0DemandedElts =
17590 EVT VT =
N->getValueType(0);
17597 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17598 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17602 LHS.getOperand(0),
RHS.getOperand(0));
17617 int ShiftAmt =
C->getSExtValue();
17618 if (ShiftAmt == 0) {
17624 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17625 unsigned NewOpcode =
17626 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17641 unsigned IntNo =
N->getConstantOperandVal(0);
17652 case Intrinsic::arm_neon_vshifts:
17653 case Intrinsic::arm_neon_vshiftu:
17654 case Intrinsic::arm_neon_vrshifts:
17655 case Intrinsic::arm_neon_vrshiftu:
17656 case Intrinsic::arm_neon_vrshiftn:
17657 case Intrinsic::arm_neon_vqshifts:
17658 case Intrinsic::arm_neon_vqshiftu:
17659 case Intrinsic::arm_neon_vqshiftsu:
17660 case Intrinsic::arm_neon_vqshiftns:
17661 case Intrinsic::arm_neon_vqshiftnu:
17662 case Intrinsic::arm_neon_vqshiftnsu:
17663 case Intrinsic::arm_neon_vqrshiftns:
17664 case Intrinsic::arm_neon_vqrshiftnu:
17665 case Intrinsic::arm_neon_vqrshiftnsu: {
17666 EVT VT =
N->getOperand(1).getValueType();
17668 unsigned VShiftOpc = 0;
17671 case Intrinsic::arm_neon_vshifts:
17672 case Intrinsic::arm_neon_vshiftu:
17674 VShiftOpc = ARMISD::VSHLIMM;
17677 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17678 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17679 : ARMISD::VSHRuIMM);
17684 case Intrinsic::arm_neon_vrshifts:
17685 case Intrinsic::arm_neon_vrshiftu:
17690 case Intrinsic::arm_neon_vqshifts:
17691 case Intrinsic::arm_neon_vqshiftu:
17696 case Intrinsic::arm_neon_vqshiftsu:
17701 case Intrinsic::arm_neon_vrshiftn:
17702 case Intrinsic::arm_neon_vqshiftns:
17703 case Intrinsic::arm_neon_vqshiftnu:
17704 case Intrinsic::arm_neon_vqshiftnsu:
17705 case Intrinsic::arm_neon_vqrshiftns:
17706 case Intrinsic::arm_neon_vqrshiftnu:
17707 case Intrinsic::arm_neon_vqrshiftnsu:
17719 case Intrinsic::arm_neon_vshifts:
17720 case Intrinsic::arm_neon_vshiftu:
17723 case Intrinsic::arm_neon_vrshifts:
17724 VShiftOpc = ARMISD::VRSHRsIMM;
17726 case Intrinsic::arm_neon_vrshiftu:
17727 VShiftOpc = ARMISD::VRSHRuIMM;
17729 case Intrinsic::arm_neon_vrshiftn:
17730 VShiftOpc = ARMISD::VRSHRNIMM;
17732 case Intrinsic::arm_neon_vqshifts:
17733 VShiftOpc = ARMISD::VQSHLsIMM;
17735 case Intrinsic::arm_neon_vqshiftu:
17736 VShiftOpc = ARMISD::VQSHLuIMM;
17738 case Intrinsic::arm_neon_vqshiftsu:
17739 VShiftOpc = ARMISD::VQSHLsuIMM;
17741 case Intrinsic::arm_neon_vqshiftns:
17742 VShiftOpc = ARMISD::VQSHRNsIMM;
17744 case Intrinsic::arm_neon_vqshiftnu:
17745 VShiftOpc = ARMISD::VQSHRNuIMM;
17747 case Intrinsic::arm_neon_vqshiftnsu:
17748 VShiftOpc = ARMISD::VQSHRNsuIMM;
17750 case Intrinsic::arm_neon_vqrshiftns:
17751 VShiftOpc = ARMISD::VQRSHRNsIMM;
17753 case Intrinsic::arm_neon_vqrshiftnu:
17754 VShiftOpc = ARMISD::VQRSHRNuIMM;
17756 case Intrinsic::arm_neon_vqrshiftnsu:
17757 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17762 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17763 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17766 case Intrinsic::arm_neon_vshiftins: {
17767 EVT VT =
N->getOperand(1).getValueType();
17769 unsigned VShiftOpc = 0;
17772 VShiftOpc = ARMISD::VSLIIMM;
17773 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17774 VShiftOpc = ARMISD::VSRIIMM;
17780 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17781 N->getOperand(1),
N->getOperand(2),
17785 case Intrinsic::arm_neon_vqrshifts:
17786 case Intrinsic::arm_neon_vqrshiftu:
17790 case Intrinsic::arm_neon_vbsl: {
17792 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17793 N->getOperand(2),
N->getOperand(3));
17795 case Intrinsic::arm_mve_vqdmlah:
17796 case Intrinsic::arm_mve_vqdmlash:
17797 case Intrinsic::arm_mve_vqrdmlah:
17798 case Intrinsic::arm_mve_vqrdmlash:
17799 case Intrinsic::arm_mve_vmla_n_predicated:
17800 case Intrinsic::arm_mve_vmlas_n_predicated:
17801 case Intrinsic::arm_mve_vqdmlah_predicated:
17802 case Intrinsic::arm_mve_vqdmlash_predicated:
17803 case Intrinsic::arm_mve_vqrdmlah_predicated:
17804 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17809 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17816 case Intrinsic::arm_mve_minv:
17817 case Intrinsic::arm_mve_maxv:
17818 case Intrinsic::arm_mve_minav:
17819 case Intrinsic::arm_mve_maxav:
17820 case Intrinsic::arm_mve_minv_predicated:
17821 case Intrinsic::arm_mve_maxv_predicated:
17822 case Intrinsic::arm_mve_minav_predicated:
17823 case Intrinsic::arm_mve_maxav_predicated: {
17826 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17833 case Intrinsic::arm_mve_addv: {
17836 bool Unsigned =
N->getConstantOperandVal(2);
17837 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17841 case Intrinsic::arm_mve_addlv:
17842 case Intrinsic::arm_mve_addlv_predicated: {
17845 bool Unsigned =
N->getConstantOperandVal(2);
17846 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17847 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17848 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17851 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17853 Ops.push_back(
N->getOperand(i));
17866 EVT VT =
Y.getValueType();
17869 if (Subtarget->hasMVEIntegerOps())
17871 if (Subtarget->hasNEON())
17885 EVT VT =
N->getValueType(0);
17887 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17888 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17889 N->getOperand(0)->hasOneUse()) {
17906 if (AndMask == 255 || AndMask == 65535)
17910 if (MaskedBits > ShiftAmt) {
17925 if (ST->hasMVEIntegerOps())
17930 switch (
N->getOpcode()) {
17936 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17943 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17944 unsigned VShiftOpc =
17945 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17947 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17963 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17966 EVT FromVT = LD->getValueType(0);
17967 EVT ToVT =
N->getValueType(0);
17974 unsigned NumElements = 0;
17975 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17977 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17979 if (NumElements == 0 ||
17989 SDValue BasePtr = LD->getBasePtr();
17990 Align Alignment = LD->getBaseAlign();
18011 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18012 Alignment, MMOFlags, AAInfo);
18018 if (FromEltVT == MVT::f16) {
18021 for (
unsigned i = 0; i < Loads.
size(); i++) {
18023 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
18042 EVT VT =
N->getValueType(0);
18049 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
18056 if (VT == MVT::i32 &&
18057 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
18062 switch (
N->getOpcode()) {
18065 Opc = ARMISD::VGETLANEs;
18069 Opc = ARMISD::VGETLANEu;
18076 if (ST->hasMVEIntegerOps())
18094 Ops.push_back(Ext);
18104 if (ST->hasMVEFloatOps())
18115 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
18119 EVT VT =
Op.getValueType();
18122 if (VT != MVT::i32 ||
18138 APInt MaxC = Max.getConstantOperandAPInt(1);
18139 if (MaxC.
sgt(MinC))
18146 if ((MinC + 1).isPowerOf2()) {
18168 APInt Width = MinC - MaxC + 1;
18171 unsigned SatBit = Width.
logBase2() - 1;
18189 EVT VT =
N->getValueType(0);
18192 if (VT == MVT::i32)
18195 if (!ST->hasMVEIntegerOps())
18201 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18204 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18212 if (VT == MVT::v4i32)
18213 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18215 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18222 MaxC != ~SaturateC)
18227 if (IsSignedSaturate(
N, N0.
getNode())) {
18230 if (VT == MVT::v4i32) {
18231 HalfVT = MVT::v8i16;
18232 ExtVT = MVT::v4i16;
18234 HalfVT = MVT::v16i8;
18249 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18255 if (VT == MVT::v4i32)
18256 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18258 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18267 if (IsUnsignedSaturate(
N)) {
18271 if (VT == MVT::v4i32) {
18272 HalfVT = MVT::v8i16;
18273 ExtConst = 0x0000FFFF;
18275 HalfVT = MVT::v16i8;
18297 const APInt *CV = &
C->getAPIntValue();
18354 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18361 if ((OrCI &
Known.Zero) != OrCI)
18367 EVT VT =
X.getValueType();
18368 unsigned BitInX = AndC->
logBase2();
18376 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18377 BitInY < NumActiveBits; ++BitInY) {
18378 if (OrCI[BitInY] == 0)
18381 Mask.setBit(BitInY);
18382 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18398 switch (
N->getOpcode()) {
18413 if (Const->isZero())
18415 else if (Const->isOne())
18423 unsigned IntOp =
N.getConstantOperandVal(1);
18424 if (IntOp != Intrinsic::test_start_loop_iterations &&
18425 IntOp != Intrinsic::loop_decrement_reg)
18451 bool Negate =
false;
18457 Cond =
N->getOperand(1);
18458 Dest =
N->getOperand(2);
18462 Cond =
N->getOperand(2);
18463 Dest =
N->getOperand(4);
18465 if (!Const->isOne() && !Const->isZero())
18467 Imm = Const->getZExtValue();
18495 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18496 "unsupported condition");
18501 unsigned IntOp =
Int->getConstantOperandVal(1);
18502 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18503 "expected single br user");
18504 SDNode *Br = *
N->user_begin();
18514 if (IntOp == Intrinsic::test_start_loop_iterations) {
18516 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18518 if (IsTrueIfZero(CC, Imm)) {
18520 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18524 UpdateUncondBr(Br, Dest, DAG);
18526 SDValue Ops[] = {Chain, Setup, OtherTarget};
18527 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18539 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18543 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18547 if (
Target == OtherTarget)
18548 UpdateUncondBr(Br, Dest, DAG);
18554 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18563 if (Cmp.getOpcode() != ARMISD::CMPZ)
18568 SDValue LHS = Cmp.getOperand(0);
18569 SDValue RHS = Cmp.getOperand(1);
18578 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18579 LHS->getOperand(0)->hasOneUse() &&
18583 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18595 EVT VT =
N->getValueType(0);
18596 SDValue FalseVal =
N->getOperand(0);
18597 SDValue TrueVal =
N->getOperand(1);
18605 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18612 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18615 if (Cmp.getOpcode() != ARMISD::CMPZ)
18619 SDValue LHS = Cmp.getOperand(0);
18620 SDValue RHS = Cmp.getOperand(1);
18624 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18648 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18649 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18650 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18653 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18658 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18661 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18662 LHS->getOperand(2), LHS->getOperand(3));
18672 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18676 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18678 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18687 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18720 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18732 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18752 const APInt *TrueConst;
18753 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18754 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18755 FalseVal.getOperand(1) == RHS) ||
18759 unsigned ShiftAmount = TrueConst->
logBase2();
18774 if (
Known.Zero == 0xfffffffe)
18777 else if (
Known.Zero == 0xffffff00)
18780 else if (
Known.Zero == 0xffff0000)
18793 EVT DstVT =
N->getValueType(0);
18796 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18797 EVT SrcVT = Src.getValueType();
18799 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18804 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18805 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18806 Src.getValueType().getScalarSizeInBits())
18807 Src = Src.getOperand(0);
18811 EVT SrcVT = Src.getValueType();
18812 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18813 Src.getOpcode() == ARMISD::VMVNIMM ||
18814 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18817 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18831 EVT VT =
N->getValueType(0);
18839 if (
N->getNumOperands() == 2 &&
18843 N->getOperand(0).getOperand(1),
18844 N->getOperand(1).getOperand(0),
18845 N->getOperand(1).getOperand(1));
18848 if (
N->getNumOperands() == 2 &&
18854 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18855 S0->getOperand(1) ==
S1->getOperand(1)) {
18858 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18862 ARMISD::VMOVN,
DL, VT,
18863 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18864 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18868 ARMISD::VMOVN,
DL, VT,
18869 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18870 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18878 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18879 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18880 (Op.getOpcode() == ISD::BITCAST &&
18881 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18884 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18886 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18904 int NumIns =
N->getNumOperands();
18905 assert((NumIns == 2 || NumIns == 4) &&
18906 "Expected 2 or 4 inputs to an MVETrunc");
18908 if (
N->getNumOperands() == 4)
18912 for (
int I = 0;
I < NumIns;
I++) {
18914 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18919 Ptr, MPI, StoreVT,
Align(4));
18934 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18937 EVT FromVT = LD->getMemoryVT();
18938 EVT ToVT =
N->getValueType(0);
18945 unsigned NumElements = 0;
18946 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18948 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18950 assert(NumElements != 0);
18956 LD->getExtensionType() != NewExtType)
18963 SDValue BasePtr = LD->getBasePtr();
18964 Align Alignment = LD->getBaseAlign();
18983 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18984 Alignment, MMOFlags, AAInfo);
19000 EVT VT =
N->getValueType(0);
19002 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
19003 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
19005 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19007 auto Extend = [&](
SDValue V) {
19016 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
19017 SDValue Ext = Extend(
N->getOperand(0));
19025 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
19026 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
19030 auto CheckInregMask = [&](
int Start,
int Offset) {
19032 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
19038 if (CheckInregMask(0, 0))
19040 else if (CheckInregMask(0, 1))
19041 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19042 else if (CheckInregMask(0, Mask.size()))
19044 else if (CheckInregMask(0, Mask.size() + 1))
19045 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19050 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19054 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19061 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
19072 int NumOuts =
N->getNumValues();
19073 assert((NumOuts == 2 || NumOuts == 4) &&
19074 "Expected 2 or 4 outputs to an MVEEXT");
19075 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19077 if (
N->getNumOperands() == 4)
19083 StackPtr, MPI,
Align(4));
19086 for (
int I = 0;
I < NumOuts;
I++) {
19088 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
19089 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
19094 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
19103 switch (
N->getOpcode()) {
19163 case ARMISD::BRCOND:
19167 case ARMISD::CSINC:
19168 case ARMISD::CSINV:
19169 case ARMISD::CSNEG:
19182 case ARMISD::PREDICATE_CAST:
19184 case ARMISD::VECTOR_REG_CAST:
19195 case ARMISD::VADDVs:
19196 case ARMISD::VADDVu:
19197 case ARMISD::VADDLVs:
19198 case ARMISD::VADDLVu:
19199 case ARMISD::VADDLVAs:
19200 case ARMISD::VADDLVAu:
19201 case ARMISD::VMLAVs:
19202 case ARMISD::VMLAVu:
19203 case ARMISD::VMLALVs:
19204 case ARMISD::VMLALVu:
19205 case ARMISD::VMLALVAs:
19206 case ARMISD::VMLALVAu:
19208 case ARMISD::VMOVN:
19210 case ARMISD::VQMOVNs:
19211 case ARMISD::VQMOVNu:
19213 case ARMISD::VQDMULH:
19219 case ARMISD::SMULWB: {
19220 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19226 case ARMISD::SMULWT: {
19227 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19233 case ARMISD::SMLALBB:
19234 case ARMISD::QADD16b:
19235 case ARMISD::QSUB16b:
19236 case ARMISD::UQADD16b:
19237 case ARMISD::UQSUB16b: {
19238 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19245 case ARMISD::SMLALBT: {
19246 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19248 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19255 case ARMISD::SMLALTB: {
19256 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19258 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19265 case ARMISD::SMLALTT: {
19266 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19273 case ARMISD::QADD8b:
19274 case ARMISD::QSUB8b:
19275 case ARMISD::UQADD8b:
19276 case ARMISD::UQSUB8b: {
19277 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19285 if (
N->getOperand(1) ==
N->getOperand(2))
19286 return N->getOperand(1);
19290 switch (
N->getConstantOperandVal(1)) {
19291 case Intrinsic::arm_neon_vld1:
19292 case Intrinsic::arm_neon_vld1x2:
19293 case Intrinsic::arm_neon_vld1x3:
19294 case Intrinsic::arm_neon_vld1x4:
19295 case Intrinsic::arm_neon_vld2:
19296 case Intrinsic::arm_neon_vld3:
19297 case Intrinsic::arm_neon_vld4:
19298 case Intrinsic::arm_neon_vld2lane:
19299 case Intrinsic::arm_neon_vld3lane:
19300 case Intrinsic::arm_neon_vld4lane:
19301 case Intrinsic::arm_neon_vld2dup:
19302 case Intrinsic::arm_neon_vld3dup:
19303 case Intrinsic::arm_neon_vld4dup:
19304 case Intrinsic::arm_neon_vst1:
19305 case Intrinsic::arm_neon_vst1x2:
19306 case Intrinsic::arm_neon_vst1x3:
19307 case Intrinsic::arm_neon_vst1x4:
19308 case Intrinsic::arm_neon_vst2:
19309 case Intrinsic::arm_neon_vst3:
19310 case Intrinsic::arm_neon_vst4:
19311 case Intrinsic::arm_neon_vst2lane:
19312 case Intrinsic::arm_neon_vst3lane:
19313 case Intrinsic::arm_neon_vst4lane:
19315 case Intrinsic::arm_mve_vld2q:
19316 case Intrinsic::arm_mve_vld4q:
19317 case Intrinsic::arm_mve_vst2q:
19318 case Intrinsic::arm_mve_vst4q:
19335 unsigned *
Fast)
const {
19341 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19344 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19346 if (AllowsUnaligned) {
19348 *
Fast = Subtarget->hasV7Ops();
19353 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19357 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19364 if (!Subtarget->hasMVEIntegerOps())
19368 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19369 Ty == MVT::v2i1)) {
19377 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19393 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19394 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19395 Ty == MVT::v2f64) {
19406 const AttributeList &FuncAttributes)
const {
19408 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19409 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19411 if (
Op.size() >= 16 &&
19417 }
else if (
Op.size() >= 8 &&
19434 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19436 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19438 return (SrcBits == 64 && DestBits == 32);
19447 return (SrcBits == 64 && DestBits == 32);
19483 return Subtarget->hasFullFP16();
19490 if (!Subtarget->hasMVEIntegerOps())
19509 if (Ld->isExpandingLoad())
19513 if (Subtarget->hasMVEIntegerOps())
19526 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19558bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19560 if (Subtarget->useSoftFloat())
19569 return Subtarget->hasMVEFloatOps();
19587 unsigned Scale = 1;
19604 if ((V & (Scale - 1)) != 0)
19613 if (VT.
isVector() && Subtarget->hasNEON())
19616 !Subtarget->hasMVEFloatOps())
19619 bool IsNeg =
false;
19625 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19628 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19644 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19650 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19680 default:
return false;
19699 int Scale = AM.
Scale;
19704 default:
return false;
19712 Scale = Scale & ~1;
19713 return Scale == 2 || Scale == 4 || Scale == 8;
19730 if (Scale & 1)
return false;
19737 const int Scale = AM.
Scale;
19747 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19763 switch (AM.
Scale) {
19774 if (Subtarget->isThumb1Only())
19777 if (Subtarget->isThumb2())
19780 int Scale = AM.
Scale;
19782 default:
return false;
19786 if (Scale < 0) Scale = -Scale;
19794 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19807 if (Scale & 1)
return false;
19820 if (!Subtarget->isThumb())
19823 if (Subtarget->isThumb2())
19827 return Imm >= 0 && Imm <= 255;
19837 if (!Subtarget->isThumb())
19839 if (Subtarget->isThumb2())
19842 return AbsImm <= 255;
19877 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19881 int RHSC = (int)
RHS->getZExtValue();
19882 if (RHSC < 0 && RHSC > -256) {
19892 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19895 int RHSC = (int)
RHS->getZExtValue();
19896 if (RHSC < 0 && RHSC > -0x1000) {
19938 int RHSC = (int)
RHS->getZExtValue();
19939 if (RHSC < 0 && RHSC > -0x100) {
19944 }
else if (RHSC > 0 && RHSC < 0x100) {
19955 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19966 bool CanChangeType = isLE && !IsMasked;
19969 int RHSC = (int)
RHS->getZExtValue();
19971 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19972 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19977 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19988 if (VT == MVT::v4i16) {
19989 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19991 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19992 if (IsInRange(RHSC, 0x80, 1))
19994 }
else if (Alignment >= 4 &&
19995 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19996 IsInRange(RHSC, 0x80, 4))
19998 else if (Alignment >= 2 &&
19999 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
20000 IsInRange(RHSC, 0x80, 2))
20002 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
20015 if (Subtarget->isThumb1Only())
20022 bool isSEXTLoad =
false;
20023 bool IsMasked =
false;
20025 Ptr = LD->getBasePtr();
20026 VT = LD->getMemoryVT();
20027 Alignment = LD->getAlign();
20028 AS = LD->getAddressSpace();
20031 Ptr = ST->getBasePtr();
20032 VT = ST->getMemoryVT();
20033 Alignment = ST->getAlign();
20034 AS = ST->getAddressSpace();
20036 Ptr = LD->getBasePtr();
20037 VT = LD->getMemoryVT();
20038 Alignment = LD->getAlign();
20039 AS = LD->getAddressSpace();
20043 Ptr = ST->getBasePtr();
20044 VT = ST->getMemoryVT();
20045 Alignment = ST->getAlign();
20046 AS = ST->getAddressSpace();
20061 bool isLegal =
false;
20063 isLegal = Subtarget->hasMVEIntegerOps() &&
20065 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
20066 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
20068 if (Subtarget->isThumb2())
20093 bool isSEXTLoad =
false, isNonExt;
20094 bool IsMasked =
false;
20096 VT = LD->getMemoryVT();
20097 Ptr = LD->getBasePtr();
20098 Alignment = LD->getAlign();
20102 VT = ST->getMemoryVT();
20103 Ptr = ST->getBasePtr();
20104 Alignment = ST->getAlign();
20105 isNonExt = !ST->isTruncatingStore();
20107 VT = LD->getMemoryVT();
20108 Ptr = LD->getBasePtr();
20109 Alignment = LD->getAlign();
20114 VT = ST->getMemoryVT();
20115 Ptr = ST->getBasePtr();
20116 Alignment = ST->getAlign();
20117 isNonExt = !ST->isTruncatingStore();
20122 if (Subtarget->isThumb1Only()) {
20125 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
20126 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
20129 if (!RHS || RHS->getZExtValue() != 4)
20131 if (Alignment <
Align(4))
20135 Base =
Op->getOperand(0);
20141 bool isLegal =
false;
20143 isLegal = Subtarget->hasMVEIntegerOps() &&
20148 if (Subtarget->isThumb2())
20162 !Subtarget->isThumb2())
20176 const APInt &DemandedElts,
20178 unsigned Depth)
const {
20181 switch (
Op.getOpcode()) {
20188 if (
Op.getResNo() == 0) {
20199 case ARMISD::CMOV: {
20202 if (
Known.isUnknown())
20214 case Intrinsic::arm_ldaex:
20215 case Intrinsic::arm_ldrex: {
20223 case ARMISD::BFI: {
20230 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20231 Known.Zero &= Mask;
20235 case ARMISD::VGETLANEs:
20236 case ARMISD::VGETLANEu: {
20237 const SDValue &SrcSV =
Op.getOperand(0);
20243 "VGETLANE index out of bounds");
20248 EVT VT =
Op.getValueType();
20254 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20262 case ARMISD::VMOVrh: {
20268 case ARMISD::CSINC:
20269 case ARMISD::CSINV:
20270 case ARMISD::CSNEG: {
20278 if (
Op.getOpcode() == ARMISD::CSINC)
20281 else if (
Op.getOpcode() == ARMISD::CSINV)
20283 else if (
Op.getOpcode() == ARMISD::CSNEG)
20290 case ARMISD::VORRIMM:
20291 case ARMISD::VBICIMM: {
20292 unsigned Encoded =
Op.getConstantOperandVal(1);
20293 unsigned DecEltBits = 0;
20296 unsigned EltBits =
Op.getScalarValueSizeInBits();
20297 if (EltBits != DecEltBits) {
20306 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20307 APInt Imm(DecEltBits, DecodedVal);
20309 Known.One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20310 Known.Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20318 if (!Subtarget->isThumb())
20335 if (Imm == 0 || Imm == ~0U)
20338 unsigned Opc =
Op.getOpcode();
20340 EVT VT =
Op.getValueType();
20342 unsigned ShrunkImm = Imm & Demanded;
20343 unsigned ExpandedImm = Imm | ~Demanded;
20345 auto IsLegalImm = [ShrunkImm, ExpandedImm](
unsigned CandidateImm) ->
bool {
20346 return (ShrunkImm & CandidateImm) == ShrunkImm &&
20347 (~ExpandedImm & CandidateImm) == 0;
20349 auto UseImm = [Imm,
Opc,
Op, VT, &TLO](
unsigned NewImm) ->
bool {
20361 if (ShrunkImm == 0) {
20362 ++NumOptimizedImms;
20363 return UseImm(ShrunkImm);
20369 if (ExpandedImm == ~0U) {
20370 ++NumOptimizedImms;
20371 return UseImm(ExpandedImm);
20379 if (IsLegalImm(0xFF)) {
20380 ++NumOptimizedImms;
20381 return UseImm(0xFF);
20384 if (IsLegalImm(0xFFFF)) {
20385 ++NumOptimizedImms;
20386 return UseImm(0xFFFF);
20400 ++NumOptimizedImms;
20401 return UseImm(ShrunkImm);
20409 if ((~ExpandedImm) < 256) {
20410 ++NumOptimizedImms;
20411 return UseImm(ExpandedImm);
20417 !Subtarget->hasV6Ops()) {
20418 ++NumOptimizedImms;
20419 return UseImm(ExpandedImm);
20438 EVT VT =
Op.getValueType();
20453 switch (
Op.getOpcode()) {
20464 unsigned Imm =
C->getZExtValue();
20471 unsigned Depth)
const {
20472 unsigned Opc =
Op.getOpcode();
20476 case ARMISD::LSRL: {
20480 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20482 unsigned ShAmt =
Op->getConstantOperandVal(2);
20492 case ARMISD::VBICIMM: {
20494 unsigned ModImm =
Op.getConstantOperandVal(1);
20495 unsigned EltBits = 0;
20497 if ((OriginalDemandedBits & Mask) == 0)
20503 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
20518 if (!Subtarget->hasVFP2Base())
20522 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20534 unsigned S = Constraint.
size();
20536 switch (Constraint[0]) {
20548 }
else if (S == 2) {
20549 switch (Constraint[0]) {
20566 Value *CallOperandVal =
info.CallOperandVal;
20569 if (!CallOperandVal)
20573 switch (*constraint) {
20579 if (Subtarget->isThumb())
20594 if (PR == 0 || VT == MVT::Other)
20596 if (ARM::SPRRegClass.
contains(PR))
20597 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20598 if (ARM::DPRRegClass.
contains(PR))
20603using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20607 switch (Constraint.
size()) {
20610 switch (Constraint[0]) {
20612 if (Subtarget->isThumb())
20613 return RCPair(0U, &ARM::tGPRRegClass);
20614 return RCPair(0U, &ARM::GPRRegClass);
20616 if (Subtarget->isThumb())
20617 return RCPair(0U, &ARM::hGPRRegClass);
20620 if (Subtarget->isThumb1Only())
20621 return RCPair(0U, &ARM::tGPRRegClass);
20622 return RCPair(0U, &ARM::GPRRegClass);
20624 if (VT == MVT::Other)
20626 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20627 return RCPair(0U, &ARM::SPRRegClass);
20629 return RCPair(0U, &ARM::DPRRegClass);
20631 return RCPair(0U, &ARM::QPRRegClass);
20634 if (VT == MVT::Other)
20636 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20637 return RCPair(0U, &ARM::SPR_8RegClass);
20639 return RCPair(0U, &ARM::DPR_8RegClass);
20641 return RCPair(0U, &ARM::QPR_8RegClass);
20644 if (VT == MVT::Other)
20646 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20647 return RCPair(0U, &ARM::SPRRegClass);
20649 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20651 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20657 if (Constraint[0] ==
'T') {
20658 switch (Constraint[1]) {
20662 return RCPair(0U, &ARM::tGPREvenRegClass);
20664 return RCPair(0U, &ARM::tGPROddRegClass);
20673 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20674 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20677 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20678 return std::make_pair(
unsigned(ARM::LR),
getRegClassFor(MVT::i32));
20682 return {0,
nullptr};
20690 std::vector<SDValue> &
Ops,
20695 if (Constraint.
size() != 1)
20698 char ConstraintLetter = Constraint[0];
20699 switch (ConstraintLetter) {
20702 case 'I':
case 'J':
case 'K':
case 'L':
20703 case 'M':
case 'N':
case 'O':
20708 int64_t CVal64 =
C->getSExtValue();
20709 int CVal = (int) CVal64;
20712 if (CVal != CVal64)
20715 switch (ConstraintLetter) {
20719 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20720 if (CVal >= 0 && CVal <= 65535)
20724 if (Subtarget->isThumb1Only()) {
20727 if (CVal >= 0 && CVal <= 255)
20729 }
else if (Subtarget->isThumb2()) {
20743 if (Subtarget->isThumb1Only()) {
20748 if (CVal >= -255 && CVal <= -1)
20754 if (CVal >= -4095 && CVal <= 4095)
20760 if (Subtarget->isThumb1Only()) {
20767 }
else if (Subtarget->isThumb2()) {
20787 if (Subtarget->isThumb1Only()) {
20790 if (CVal >= -7 && CVal < 7)
20792 }
else if (Subtarget->isThumb2()) {
20812 if (Subtarget->isThumb1Only()) {
20815 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20821 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20827 if (Subtarget->isThumb1Only()) {
20829 if (CVal >= 0 && CVal <= 31)
20835 if (Subtarget->isThumb1Only()) {
20838 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20847 if (Result.getNode()) {
20848 Ops.push_back(Result);
20858 "Unhandled Opcode in getDivRemLibcall");
20864 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20865 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20866 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20867 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20876 "Unhandled Opcode in getDivRemArgList");
20880 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20881 EVT ArgVT =
N->getOperand(i).getValueType();
20886 Args.push_back(Entry);
20894 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20895 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20896 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20897 "Register-based DivRem lowering only");
20898 unsigned Opcode =
Op->getOpcode();
20900 "Invalid opcode for Div/Rem lowering");
20902 EVT VT =
Op->getValueType(0);
20924 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20925 : Subtarget->hasDivideInARMMode();
20926 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20927 Op->getSimpleValueType(0) == MVT::i32) {
20929 const SDValue Dividend =
Op->getOperand(0);
20930 const SDValue Divisor =
Op->getOperand(1);
20931 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20954 if (
getTM().getTargetTriple().isOSWindows())
20957 TargetLowering::CallLoweringInfo CLI(DAG);
20961 Callee, std::move(Args))
20966 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20967 return CallInfo.first;
20973 EVT VT =
N->getValueType(0);
20979 Result[0], Result[1]);
20983 std::vector<Type*> RetTyParams;
20984 Type *RetTyElement;
20994 RetTyParams.push_back(RetTyElement);
20995 RetTyParams.push_back(RetTyElement);
21010 if (
getTM().getTargetTriple().isOSWindows())
21017 Callee, std::move(Args))
21021 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
21024 SDNode *ResNode = CallResult.first.getNode();
21031 assert(
getTM().getTargetTriple().isOSWindows() &&
21032 "unsupported target platform");
21040 "no-stack-arg-probe")) {
21044 Chain =
SP.getValue(1);
21061 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
21062 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
21072 bool IsStrict =
Op->isStrictFPOpcode();
21073 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21074 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21076 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
21077 "Unexpected type for custom-lowering FP_EXTEND");
21079 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21080 "With both FP DP and 16, any FP conversion is legal!");
21082 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
21083 "With FP16, 16 to 32 conversion is legal!");
21086 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
21091 Loc,
Op.getValueType(), SrcVal);
21106 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
21107 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
21108 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
21109 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
21113 {DstVT, MVT::Other}, {Chain, SrcVal});
21120 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21121 "Unexpected type for custom-lowering FP_EXTEND");
21122 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21127 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
21131 bool IsStrict =
Op->isStrictFPOpcode();
21133 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21135 EVT DstVT =
Op.getValueType();
21137 if (DstVT == MVT::bf16) {
21138 if (Subtarget->hasBF16() && SrcVT == MVT::f32)
21143 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21146 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
21147 "Unexpected type for custom-lowering FP_ROUND");
21149 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21150 "With both FP DP and 16, any FP conversion is legal!");
21155 if (SrcSz == 32 && Subtarget->hasFP16())
21160 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21161 "Unexpected type for custom-lowering FP_ROUND");
21165 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21177 if (v == 0xffffffff)
21189 bool ForCodeSize)
const {
21190 if (!Subtarget->hasVFP3Base())
21192 if (VT == MVT::f16 && Subtarget->hasFullFP16())
21194 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
21197 if (VT == MVT::f32)
21199 if (VT == MVT::f64 && Subtarget->hasFP64())
21212 case Intrinsic::arm_neon_vld1:
21213 case Intrinsic::arm_neon_vld2:
21214 case Intrinsic::arm_neon_vld3:
21215 case Intrinsic::arm_neon_vld4:
21216 case Intrinsic::arm_neon_vld2lane:
21217 case Intrinsic::arm_neon_vld3lane:
21218 case Intrinsic::arm_neon_vld4lane:
21219 case Intrinsic::arm_neon_vld2dup:
21220 case Intrinsic::arm_neon_vld3dup:
21221 case Intrinsic::arm_neon_vld4dup: {
21224 auto &
DL =
I.getDataLayout();
21225 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21227 Info.ptrVal =
I.getArgOperand(0);
21229 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21236 case Intrinsic::arm_neon_vld1x2:
21237 case Intrinsic::arm_neon_vld1x3:
21238 case Intrinsic::arm_neon_vld1x4: {
21241 auto &
DL =
I.getDataLayout();
21242 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21244 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
21246 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
21252 case Intrinsic::arm_neon_vst1:
21253 case Intrinsic::arm_neon_vst2:
21254 case Intrinsic::arm_neon_vst3:
21255 case Intrinsic::arm_neon_vst4:
21256 case Intrinsic::arm_neon_vst2lane:
21257 case Intrinsic::arm_neon_vst3lane:
21258 case Intrinsic::arm_neon_vst4lane: {
21261 auto &
DL =
I.getDataLayout();
21262 unsigned NumElts = 0;
21263 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21264 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21267 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21270 Info.ptrVal =
I.getArgOperand(0);
21272 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21279 case Intrinsic::arm_neon_vst1x2:
21280 case Intrinsic::arm_neon_vst1x3:
21281 case Intrinsic::arm_neon_vst1x4: {
21284 auto &
DL =
I.getDataLayout();
21285 unsigned NumElts = 0;
21286 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21287 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21290 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21293 Info.ptrVal =
I.getArgOperand(0);
21295 Info.align =
I.getParamAlign(0).valueOrOne();
21301 case Intrinsic::arm_mve_vld2q:
21302 case Intrinsic::arm_mve_vld4q: {
21306 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21308 Info.ptrVal =
I.getArgOperand(0);
21316 case Intrinsic::arm_mve_vst2q:
21317 case Intrinsic::arm_mve_vst4q: {
21320 Type *VecTy =
I.getArgOperand(1)->getType();
21321 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21323 Info.ptrVal =
I.getArgOperand(0);
21331 case Intrinsic::arm_mve_vldr_gather_base:
21332 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21334 Info.ptrVal =
nullptr;
21336 Info.align =
Align(1);
21341 case Intrinsic::arm_mve_vldr_gather_base_wb:
21342 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21344 Info.ptrVal =
nullptr;
21345 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21346 Info.align =
Align(1);
21351 case Intrinsic::arm_mve_vldr_gather_offset:
21352 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21354 Info.ptrVal =
nullptr;
21359 Info.align =
Align(1);
21364 case Intrinsic::arm_mve_vstr_scatter_base:
21365 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21367 Info.ptrVal =
nullptr;
21368 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21369 Info.align =
Align(1);
21374 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21375 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21377 Info.ptrVal =
nullptr;
21378 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21379 Info.align =
Align(1);
21384 case Intrinsic::arm_mve_vstr_scatter_offset:
21385 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21387 Info.ptrVal =
nullptr;
21392 Info.align =
Align(1);
21397 case Intrinsic::arm_ldaex:
21398 case Intrinsic::arm_ldrex: {
21399 auto &
DL =
I.getDataLayout();
21400 Type *ValTy =
I.getParamElementType(0);
21403 Info.ptrVal =
I.getArgOperand(0);
21405 Info.align =
DL.getABITypeAlign(ValTy);
21410 case Intrinsic::arm_stlex:
21411 case Intrinsic::arm_strex: {
21412 auto &
DL =
I.getDataLayout();
21413 Type *ValTy =
I.getParamElementType(1);
21416 Info.ptrVal =
I.getArgOperand(1);
21418 Info.align =
DL.getABITypeAlign(ValTy);
21423 case Intrinsic::arm_stlexd:
21424 case Intrinsic::arm_strexd:
21426 Info.memVT = MVT::i64;
21427 Info.ptrVal =
I.getArgOperand(2);
21429 Info.align =
Align(8);
21434 case Intrinsic::arm_ldaexd:
21435 case Intrinsic::arm_ldrexd:
21437 Info.memVT = MVT::i64;
21438 Info.ptrVal =
I.getArgOperand(0);
21440 Info.align =
Align(8);
21454 assert(Ty->isIntegerTy());
21456 unsigned Bits = Ty->getPrimitiveSizeInBits();
21457 if (Bits == 0 || Bits > 32)
21463 unsigned Index)
const {
21473 if (!Subtarget->hasDataBarrier()) {
21477 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21478 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21479 Builder.getInt32(0), Builder.getInt32(7),
21480 Builder.getInt32(10), Builder.getInt32(5)};
21481 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_mcr,
args);
21490 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_dmb, CDomain);
21511 if (Subtarget->preferISHSTBarriers())
21544 bool has64BitAtomicStore;
21545 if (Subtarget->isMClass())
21546 has64BitAtomicStore =
false;
21547 else if (Subtarget->isThumb())
21548 has64BitAtomicStore = Subtarget->hasV7Ops();
21550 has64BitAtomicStore = Subtarget->hasV6Ops();
21552 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21566 bool has64BitAtomicLoad;
21567 if (Subtarget->isMClass())
21568 has64BitAtomicLoad =
false;
21569 else if (Subtarget->isThumb())
21570 has64BitAtomicLoad = Subtarget->hasV7Ops();
21572 has64BitAtomicLoad = Subtarget->hasV6Ops();
21588 if (Subtarget->isMClass())
21589 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21590 else if (Subtarget->isThumb())
21591 hasAtomicRMW = Subtarget->hasV7Ops();
21593 hasAtomicRMW = Subtarget->hasV6Ops();
21594 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21618 bool HasAtomicCmpXchg;
21619 if (Subtarget->isMClass())
21620 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21621 else if (Subtarget->isThumb())
21622 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21624 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21626 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21633 return InsertFencesForAtomic;
21638 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21644 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21645 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21647 RTLIB::LibcallImpl SecurityCookieVar =
21648 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21649 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21650 SecurityCookieVar != RTLIB::Unsupported) {
21661 F->addParamAttr(0, Attribute::AttrKind::InReg);
21668 unsigned &
Cost)
const {
21670 if (!Subtarget->hasNEON())
21699 unsigned Opcode =
Op.getOpcode();
21701 case ARMISD::VORRIMM:
21702 case ARMISD::VBICIMM:
21706 Op, DemandedElts, DAG, Kind, ConsiderFlags,
Depth);
21710 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21714 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21719 if (!Subtarget->hasV7Ops())
21725 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21727 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21735 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21744 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21750 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21752 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21755 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21757 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21758 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21759 if (!Subtarget->isLittle())
21761 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21762 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21763 return Builder.CreateOr(
21764 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21768 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21769 CallInst *CI = Builder.CreateIntrinsicWithoutFolding(
Int, Tys, Addr);
21772 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21773 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21778 if (!Subtarget->hasV7Ops())
21780 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21786 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21794 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21797 Value *
Lo = Builder.CreateTrunc(Val, Int32Ty,
"lo");
21798 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32), Int32Ty,
"hi");
21799 if (!Subtarget->isLittle())
21801 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21804 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21808 CallInst *CI = Builder.CreateCall(
21809 Strex, {Builder.CreateZExtOrBitCast(
21819 return Subtarget->isMClass();
21827 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21834 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21837 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21845 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21853 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21856 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21861 if (Subtarget->hasNEON() && VecSize == 64)
21863 return VecSize % 128 == 0;
21867 if (Subtarget->hasNEON())
21869 if (Subtarget->hasMVEIntegerOps())
21889 "Invalid interleave factor");
21890 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21892 "Unmatched number of shufflevectors and indices");
21897 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21900 Type *EltTy = VecTy->getElementType();
21903 Align Alignment = LI->getAlign();
21921 Value *BaseAddr = LI->getPointerOperand();
21923 if (NumLoads > 1) {
21927 VecTy->getNumElements() / NumLoads);
21933 if (Subtarget->hasNEON()) {
21934 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21935 Type *Tys[] = {VecTy, PtrTy};
21936 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21937 Intrinsic::arm_neon_vld3,
21938 Intrinsic::arm_neon_vld4};
21941 Ops.push_back(BaseAddr);
21942 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21944 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21947 assert((Factor == 2 || Factor == 4) &&
21948 "expected interleave factor of 2 or 4 for MVE");
21950 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21951 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21952 Type *Tys[] = {VecTy, PtrTy};
21955 Ops.push_back(BaseAddr);
21956 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21966 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21970 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21971 VecTy->getNumElements() * Factor);
21977 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21979 unsigned Index = Indices[i];
21981 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21985 SubVec = Builder.CreateIntToPtr(
21989 SubVecs[SV].push_back(SubVec);
21998 auto &SubVec = SubVecs[SVI];
22001 SVI->replaceAllUsesWith(WideVec);
22037 const APInt &GapMask)
const {
22039 "Invalid interleave factor");
22044 "Unexpected mask on store");
22047 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
22049 unsigned LaneLen = VecTy->getNumElements() / Factor;
22050 Type *EltTy = VecTy->getElementType();
22054 Align Alignment =
SI->getAlign();
22071 Type *IntTy =
DL.getIntPtrType(EltTy);
22076 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
22077 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
22083 Value *BaseAddr =
SI->getPointerOperand();
22085 if (NumStores > 1) {
22088 LaneLen /= NumStores;
22098 if (Subtarget->hasNEON()) {
22099 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
22100 Intrinsic::arm_neon_vst3,
22101 Intrinsic::arm_neon_vst4};
22102 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22103 Type *Tys[] = {PtrTy, SubVecTy};
22106 Ops.push_back(BaseAddr);
22108 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
22109 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
22111 assert((Factor == 2 || Factor == 4) &&
22112 "expected interleave factor of 2 or 4 for MVE");
22114 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
22115 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22116 Type *Tys[] = {PtrTy, SubVecTy};
22119 Ops.push_back(BaseAddr);
22121 for (
unsigned F = 0;
F < Factor;
F++) {
22122 Ops.push_back(Builder.getInt32(
F));
22123 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
22129 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
22132 if (StoreCount > 0)
22133 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
22134 BaseAddr, LaneLen * Factor);
22139 for (
unsigned i = 0; i < Factor; i++) {
22140 unsigned IdxI = StoreCount * LaneLen * Factor + i;
22141 if (Mask[IdxI] >= 0) {
22142 Shuffles.
push_back(Builder.CreateShuffleVector(
22145 unsigned StartMask = 0;
22146 for (
unsigned j = 1; j < LaneLen; j++) {
22147 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
22148 if (Mask[IdxJ * Factor + IdxI] >= 0) {
22149 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
22159 Shuffles.
push_back(Builder.CreateShuffleVector(
22180 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
22184 Members += SubMembers;
22190 Members += SubMembers * AT->getNumElements();
22191 }
else if (Ty->isFloatTy()) {
22196 }
else if (Ty->isDoubleTy()) {
22208 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
22210 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
22212 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
22225 return (Members > 0 && Members <= 4);
22231 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
22233 return ABITypeAlign;
22238 assert(StackAlign &&
"data layout string is missing stack alignment");
22239 return std::min(ABITypeAlign, *StackAlign);
22248 if (getEffectiveCallingConv(CallConv, isVarArg) !=
22257 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
22258 return IsHA || IsIntArray;
22262 const Constant *PersonalityFn)
const {
22270 const Constant *PersonalityFn)
const {
22283void ARMTargetLowering::insertCopiesSplitCSR(
22287 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22297 RC = &ARM::GPRRegClass;
22298 else if (ARM::DPRRegClass.
contains(*
I))
22299 RC = &ARM::DPRRegClass;
22309 assert(Entry->getParent()->getFunction().hasFnAttribute(
22310 Attribute::NoUnwind) &&
22311 "Function should be nounwind in insertCopiesSplitCSR!");
22312 Entry->addLiveIn(*
I);
22317 for (
auto *Exit : Exits)
22319 TII->get(TargetOpcode::COPY), *
I)
22330 return Subtarget->hasMVEIntegerOps();
22340 unsigned NumElements = VTy->getNumElements();
22347 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22348 return Subtarget->hasMVEFloatOps();
22353 return Subtarget->hasMVEIntegerOps() &&
22354 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22355 ScalarTy->isIntegerTy(32));
22359 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22370 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22372 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22374 if (TyWidth > 128) {
22375 int Stride = Ty->getNumElements() / 2;
22379 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22381 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22382 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22383 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22384 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22385 Value *LowerSplitAcc =
nullptr;
22386 Value *UpperSplitAcc =
nullptr;
22389 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22390 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22394 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22396 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22398 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22399 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22406 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22409 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22411 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22412 {ConstRotation, InputB, InputA});
22417 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22420 ConstRotation = ConstantInt::get(IntTy, 0);
22422 ConstRotation = ConstantInt::get(IntTy, 1);
22424 if (!ConstRotation)
22427 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22428 {ConstHalving, ConstRotation, InputA, InputB});
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static SDValue carryFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG, bool Invert)
static SDValue overflowFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue valueToCarryFlag(SDValue Value, SelectionDAG &DAG, bool Invert)
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static unsigned getCmpOperandFoldingProfit(SDValue Op, bool AllowExtend)
Returns how profitable it is to fold a comparison's operand's shift and/or extension operations.
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static bool optimizeLogicalImm(SDValue Op, unsigned Size, uint64_t Imm, const APInt &Demanded, TargetLowering::TargetLoweringOpt &TLO, unsigned NewOpc)
static bool isSafeSignedCMN(SDValue Op, SelectionDAG &DAG)
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static SDValue matchCSET(unsigned &Opcode, bool &InvertCond, SDValue TrueVal, SDValue FalseVal, const ARMSubtarget *Subtarget)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getInvertedARMCondCode(SDValue ARMcc, SelectionDAG &DAG)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static SDValue LowerADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG, unsigned Opcode, bool IsSigned)
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static int getNegationCost(SDValue Op)
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static bool isLegalLogicalImmediate(unsigned Imm, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static unsigned SelectPairHalf(unsigned Elements, ArrayRef< int > Mask, unsigned Index)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerTruncate(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformHWLoopCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformORCombineToShiftInsert(SelectionDAG &DAG, SDValue AndOp, SDValue ShiftOp, EVT VT, SDLoc dl)
static SDValue PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static constexpr roundingMode rmTowardZero
LLVM_ABI bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
unsigned logBase2() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool isOne() const
Determine if this is a value of 1.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
const ARMBaseRegisterInfo & getRegisterInfo() const
const uint32_t * getSjLjDispatchPreservedMask(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const uint32_t * getTLSCallPreservedMask(const MachineFunction &MF) const
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
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 constexpr BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
LLVM_ABI int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, uint32_t BitWidth) const
If this is a constant FP splat and the splatted constant FP is an exact power or 2,...
CCState - This class holds information needed while lowering arguments and return values.
void getInRegsParamInfo(unsigned InRegsParamRecordIndex, unsigned &BeginReg, unsigned &EndReg) const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
void rewindByValRegsInfo()
unsigned getInRegsParamsProcessed() const
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd)
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
unsigned getInRegsParamsCount() const
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
const APFloat & getValueAPF() const
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
MachineConstantPoolValue * getMachineCPVal() const
bool isMachineConstantPoolEntry() const
const Constant * getConstVal() const
LLVM_ABI Type * getType() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
MaybeAlign getStackAlignment() const
Returns the natural stack alignment, or MaybeAlign() if one wasn't specified.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
StringRef getInternalSymbolPrefix() const
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
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, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue 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)
static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC)
getSwappedCondition - assume the flags are set by MI(a,b), return the condition code if we modify the...
@ SECREL
Thread Pointer Offset.
@ 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
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ 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.
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)