83#include "llvm/IR/IntrinsicsARM.h"
117#define DEBUG_TYPE "arm-isel"
120STATISTIC(NumOptimizedImms,
"Number of times immediates were optimized");
121STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
122STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
124 "Number of constants with their storage promoted into constant pools");
128 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
133 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
138 cl::desc(
"Maximum size of constant to promote into a constant pool"),
142 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
147 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
152 cl::desc(
"Maximum number of base-updates to check generating postindex."),
160 ARM::R0, ARM::R1, ARM::R2, ARM::R3
174void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
175 if (VT != PromotedLdStVT) {
184 if (ElemTy != MVT::f64)
188 if (ElemTy == MVT::i32) {
232void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
234 addTypeForNEON(VT, MVT::f64);
237void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
239 addTypeForNEON(VT, MVT::v2f64);
242void ARMTargetLowering::setAllExpand(
MVT VT) {
255void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
262void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
263 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
265 for (
auto VT : IntTypes) {
340 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
341 for (
auto VT : FloatTypes) {
415 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
416 for (
auto VT : LongTypes) {
433 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
434 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
435 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
452 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
461 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
462 for (
auto VT : pTypes) {
513 RegInfo(Subtarget->getRegisterInfo()),
514 Itins(Subtarget->getInstrItineraryData()) {
520 const Triple &TT = TM.getTargetTriple();
522 if (Subtarget->isThumb1Only())
527 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
528 Subtarget->hasFPRegs()) {
532 if (!Subtarget->hasVFP2Base()) {
533 setAllExpand(MVT::f32);
542 if (!Subtarget->hasFP64()) {
543 setAllExpand(MVT::f64);
553 if (Subtarget->hasFullFP16()) {
568 if (Subtarget->hasBF16()) {
570 setAllExpand(MVT::bf16);
571 if (!Subtarget->hasFullFP16())
585 addAllExtLoads(VT, InnerVT,
Expand);
594 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
597 if (!Subtarget->hasV8_1MMainlineOps())
600 if (!Subtarget->isThumb1Only())
609 if (Subtarget->hasMVEIntegerOps())
610 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
613 if (Subtarget->hasLOB()) {
617 if (Subtarget->hasNEON()) {
618 addDRTypeForNEON(MVT::v2f32);
619 addDRTypeForNEON(MVT::v8i8);
620 addDRTypeForNEON(MVT::v4i16);
621 addDRTypeForNEON(MVT::v2i32);
622 addDRTypeForNEON(MVT::v1i64);
624 addQRTypeForNEON(MVT::v4f32);
625 addQRTypeForNEON(MVT::v2f64);
626 addQRTypeForNEON(MVT::v16i8);
627 addQRTypeForNEON(MVT::v8i16);
628 addQRTypeForNEON(MVT::v4i32);
629 addQRTypeForNEON(MVT::v2i64);
631 if (Subtarget->hasFullFP16()) {
632 addQRTypeForNEON(MVT::v8f16);
633 addDRTypeForNEON(MVT::v4f16);
636 if (Subtarget->hasBF16()) {
637 addQRTypeForNEON(MVT::v8bf16);
638 addDRTypeForNEON(MVT::v4bf16);
642 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
682 if (Subtarget->hasNEON()) {
795 if (!Subtarget->hasVFP4Base()) {
804 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
813 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
822 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
830 if (Subtarget->hasMVEIntegerOps()) {
835 if (Subtarget->hasMVEFloatOps()) {
839 if (!Subtarget->hasFP64()) {
891 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
894 if (Subtarget->hasFullFP16()) {
902 if (!Subtarget->hasFP16()) {
931 if (!Subtarget->isThumb1Only()) {
950 if (TT.isTargetAEABI() && !Subtarget->allowsUnalignedMem()) {
962 if (!Subtarget->isThumb1Only()) {
971 if (Subtarget->hasDSP()) {
981 if (Subtarget->hasBaseDSP()) {
989 if (Subtarget->isThumb1Only()) {
993 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
994 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1009 if (Subtarget->hasMVEIntegerOps())
1013 if (Subtarget->isThumb1Only()) {
1019 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1033 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1042 if (Subtarget->hasPerfMon())
1046 if (!Subtarget->hasV6Ops())
1049 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1050 : Subtarget->hasDivideInARMMode();
1057 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1069 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1070 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1073 HasStandaloneRem =
false;
1100 if (TT.isOSWindows())
1107 InsertFencesForAtomic =
false;
1108 if (Subtarget->hasAnyDataBarrier() &&
1109 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1113 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1118 if (!Subtarget->hasAcquireRelease() ||
1121 InsertFencesForAtomic =
true;
1127 if (Subtarget->hasDataBarrier())
1128 InsertFencesForAtomic =
true;
1148 if (!InsertFencesForAtomic) {
1155 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1167 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1168 Subtarget->hasForced32BitAtomics()) {
1182 if (!Subtarget->hasV6Ops()) {
1188 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1189 !Subtarget->isThumb1Only()) {
1218 if (Subtarget->hasFullFP16()) {
1228 if (Subtarget->hasFullFP16())
1243 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1244 !Subtarget->isThumb1Only()) {
1251 if (!Subtarget->hasVFP4Base()) {
1257 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1259 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1267 if (!Subtarget->hasFP16()) {
1284 if (Subtarget->hasFPARMv8Base()) {
1294 if (Subtarget->hasFP64())
1298 if (Subtarget->hasNEON()) {
1308 if (Subtarget->hasFullFP16()) {
1345 if (Subtarget->hasNEON()) {
1357 if (Subtarget->hasV8Ops()) {
1367 if (Subtarget->hasFullFP16()) {
1390 if (TT.isOSWindows()) {
1407 if (Subtarget->hasMVEIntegerOps())
1410 if (Subtarget->hasV6Ops())
1412 if (Subtarget->isThumb1Only())
1415 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1416 Subtarget->isThumb2()) {
1422 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1423 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1445 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1453 return Subtarget->useSoftFloat();
1457 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1470std::pair<const TargetRegisterClass *, uint8_t>
1481 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1482 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1483 RRC = &ARM::DPRRegClass;
1488 if (Subtarget->useNEONForSinglePrecisionFP())
1491 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1492 case MVT::v4f32:
case MVT::v2f64:
1493 RRC = &ARM::DPRRegClass;
1497 RRC = &ARM::DPRRegClass;
1501 RRC = &ARM::DPRRegClass;
1505 return std::make_pair(RRC,
Cost);
1514 if (Subtarget->hasMVEIntegerOps())
1529 if (Subtarget->hasNEON()) {
1530 if (VT == MVT::v4i64)
1531 return &ARM::QQPRRegClass;
1532 if (VT == MVT::v8i64)
1533 return &ARM::QQQQPRRegClass;
1535 if (Subtarget->hasMVEIntegerOps()) {
1536 if (VT == MVT::v4i64)
1537 return &ARM::MQQPRRegClass;
1538 if (VT == MVT::v8i64)
1539 return &ARM::MQQQQPRRegClass;
1548 Align &PrefAlign)
const {
1555 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1567 unsigned NumVals =
N->getNumValues();
1571 for (
unsigned i = 0; i != NumVals; ++i) {
1572 EVT VT =
N->getValueType(i);
1573 if (VT == MVT::Glue || VT == MVT::Other)
1579 if (!
N->isMachineOpcode())
1587 if (
MCID.getNumDefs() == 0)
1589 if (!Itins->isEmpty() &&
1590 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1604 return Const->getZExtValue() == 16;
1612 return Const->getZExtValue() == 16;
1620 return Const->getZExtValue() == 16;
1689 bool isVarArg)
const {
1708 if (!Subtarget->isAAPCS_ABI())
1710 else if (Subtarget->isTargetHardFloat() && !isVarArg)
1716 if (!Subtarget->isAAPCS_ABI()) {
1717 if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() && !isVarArg)
1720 }
else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1729 bool isVarArg)
const {
1730 return CCAssignFnForNode(CC,
false, isVarArg);
1734 bool isVarArg)
const {
1735 return CCAssignFnForNode(CC,
true, isVarArg);
1742 bool isVarArg)
const {
1769 if (Subtarget->hasFullFP16()) {
1770 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1782 if (Subtarget->hasFullFP16()) {
1783 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1796SDValue ARMTargetLowering::LowerCallResult(
1800 SDValue ThisVal,
bool isCmseNSCall)
const {
1808 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1809 CCValAssign VA = RVLocs[i];
1813 if (i == 0 && isThisReturn) {
1815 "unexpected return calling convention register assignment");
1833 if (!Subtarget->isLittle())
1835 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1850 if (!Subtarget->isLittle())
1852 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1882 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1893std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1895 bool IsTailCall,
int SPDiff)
const {
1897 MachinePointerInfo DstInfo;
1917 return std::make_pair(DstAddr, DstInfo);
1926ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1939 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1942 int SrcFI = SrcFrameIdxNode->getIndex();
1943 int DstFI = DstFrameIdxNode->getIndex();
1945 "byval passed in non-fixed stack slot");
1967 if (SrcOffset == DstOffset)
1975 RegsToPassVector &RegsToPass,
1981 SDValue fmrrd = DAG.
getNode(ARMISD::VMOVRRD, dl,
1982 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1983 unsigned id = Subtarget->isLittle() ? 0 : 1;
1995 MachinePointerInfo DstInfo;
1996 std::tie(DstAddr, DstInfo) =
1997 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2014 SelectionDAG &DAG = CLI.
DAG;
2016 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2017 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2018 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2019 SDValue Chain = CLI.
Chain;
2025 const CallBase *CB = CLI.
CB;
2028 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2030 MachineFunction::CallSiteInfo CSInfo;
2031 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2032 bool isThisReturn =
false;
2033 bool isCmseNSCall =
false;
2034 bool isSibCall =
false;
2035 bool PreferIndirect =
false;
2036 bool GuardWithBTI =
false;
2046 !Subtarget->noBTIAtReturnTwice())
2054 isCmseNSCall =
true;
2057 if (!Subtarget->supportsTailCall())
2073 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2074 count_if(GV->users(), [&BB](
const User *U) {
2075 return isa<Instruction>(U) &&
2076 cast<Instruction>(U)->getParent() == BB;
2083 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2097 "site marked musttail");
2100 unsigned NumBytes = CCInfo.getStackSize();
2109 if (isTailCall && !isSibCall) {
2110 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2111 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2116 assert(StackAlign &&
"data layout string is missing stack alignment");
2117 NumBytes =
alignTo(NumBytes, *StackAlign);
2122 SPDiff = NumReusableBytes - NumBytes;
2126 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2142 RegsToPassVector RegsToPass;
2151 DenseMap<unsigned, SDValue> ByValTemporaries;
2152 SDValue ByValTempChain;
2155 for (
const CCValAssign &VA : ArgLocs) {
2157 SDValue Src = OutVals[ArgIdx];
2158 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2160 if (!
Flags.isByVal())
2164 MachinePointerInfo DstInfo;
2165 std::tie(Dst, DstInfo) =
2166 computeAddrForCallArg(dl, DAG, VA, SDValue(),
true, SPDiff);
2167 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2169 if (Copy == NoCopy) {
2174 }
else if (Copy == CopyOnce) {
2178 ByValTemporaries[ArgIdx] = Src;
2180 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2184 int TempFrameIdx = MFI.CreateStackObject(
2185 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2193 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2194 SDValue
Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2196 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2197 ByValTemporaries[ArgIdx] = Temp;
2200 if (!ByValCopyChains.
empty())
2210 bool AfterFormalArgLoads =
false;
2214 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2216 ++i, ++realArgIdx) {
2217 CCValAssign &VA = ArgLocs[i];
2218 SDValue Arg = OutVals[realArgIdx];
2219 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2220 bool isByVal =
Flags.isByVal();
2240 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2242 if (ByValTempChain) {
2247 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2248 if (Outs[
I].
Flags.isByVal())
2251 SDValue OutVal = OutVals[
I];
2256 FrameIndexSDNode *FIN =
2261 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2264 for (
const CCValAssign &VA : ArgLocs) {
2272 if (!IncomingLoad.
empty()) {
2280 AfterFormalArgLoads =
true;
2292 auto ArgVT = Outs[realArgIdx].ArgVT;
2293 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2311 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2312 StackPtr, MemOpChains, isTailCall, SPDiff);
2316 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2317 StackPtr, MemOpChains, isTailCall, SPDiff);
2321 MachinePointerInfo DstInfo;
2322 std::tie(DstAddr, DstInfo) =
2323 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2327 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2328 StackPtr, MemOpChains, isTailCall, SPDiff);
2330 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2331 Outs[0].VT == MVT::i32) {
2333 "unexpected calling convention register assignment");
2335 "unexpected use of 'returned'");
2336 isThisReturn =
true;
2341 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2342 }
else if (isByVal) {
2344 unsigned offset = 0;
2348 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2349 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2352 bool NeedsStackCopy;
2353 if (
auto It = ByValTemporaries.
find(realArgIdx);
2354 It != ByValTemporaries.
end()) {
2355 ByValSrc = It->second;
2356 NeedsStackCopy =
true;
2359 NeedsStackCopy = !isTailCall;
2363 if (CurByValIdx < ByValArgsCount) {
2364 unsigned RegBegin, RegEnd;
2365 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2369 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2373 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2376 RegsToPass.push_back(std::make_pair(j,
Load));
2381 offset = RegEnd - RegBegin;
2383 CCInfo.nextInRegsParam();
2388 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2391 MachinePointerInfo DstInfo;
2392 std::tie(Dst, DstInfo) =
2393 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2401 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2402 SDValue
Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2409 MachinePointerInfo DstInfo;
2410 std::tie(DstAddr, DstInfo) =
2411 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2413 SDValue
Store = DAG.
getStore(Chain, dl, Arg, DstAddr, DstInfo);
2418 if (!MemOpChains.
empty())
2424 for (
const auto &[
Reg,
N] : RegsToPass) {
2432 bool isDirect =
false;
2435 const Triple &
TT = TM.getTargetTriple();
2436 const GlobalValue *GVal =
nullptr;
2438 GVal =
G->getGlobal();
2439 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2441 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2442 bool isLocalARMFunc =
false;
2445 if (Subtarget->genLongCalls()) {
2447 if (isPIC && Subtarget->genExecuteOnly())
2449 "position-independent code is not supported");
2450 if (Subtarget->isROPI())
2457 if (Subtarget->genExecuteOnly()) {
2460 if (Subtarget->useMovt())
2483 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2489 const char *Sym = S->getSymbol();
2491 if (Subtarget->genExecuteOnly()) {
2494 if (Subtarget->useMovt())
2501 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
2507 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2508 SDValue GOTOffset = DAG.
getLoad(
2511 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
2512 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, GOTOffset, PICLabel);
2524 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2531 if (!PreferIndirect) {
2536 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2538 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2539 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2541 ARMISD::WrapperPIC, dl, PtrVt,
2548 }
else if (Subtarget->isTargetCOFF()) {
2549 assert(Subtarget->isTargetWindows() &&
2550 "Windows is the only supported COFF target");
2554 else if (!TM.shouldAssumeDSOLocal(GVal))
2561 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2570 const char *Sym = S->getSymbol();
2571 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2573 ARMConstantPoolValue *CPV =
2575 ARMPCLabelIndex, 4);
2577 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2581 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
2582 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2589 assert(!isARMFunc && !isDirect &&
2590 "Cannot handle call to ARM function or direct call");
2594 "call to non-secure function would require "
2595 "passing arguments on stack",
2601 "call to non-secure function would return value through pointer",
2608 if (Subtarget->isThumb()) {
2610 CallOpc = ARMISD::t2CALL_BTI;
2611 else if (isCmseNSCall)
2612 CallOpc = ARMISD::tSECALL;
2613 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2614 CallOpc = ARMISD::CALL_NOLINK;
2616 CallOpc = ARMISD::CALL;
2618 if (!isDirect && !Subtarget->hasV5TOps())
2619 CallOpc = ARMISD::CALL_NOLINK;
2620 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2622 !Subtarget->hasMinSize())
2624 CallOpc = ARMISD::CALL_NOLINK;
2626 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2633 if (isTailCall && !isSibCall) {
2638 std::vector<SDValue>
Ops;
2639 Ops.push_back(Chain);
2640 Ops.push_back(Callee);
2648 for (
const auto &[
Reg,
N] : RegsToPass)
2652 const uint32_t *
Mask;
2653 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2661 isThisReturn =
false;
2667 assert(Mask &&
"Missing call preserved mask for calling convention");
2671 Ops.push_back(InGlue);
2675 SDValue Ret = DAG.
getNode(ARMISD::TC_RETURN, dl, MVT::Other,
Ops);
2684 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2698 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2704 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2705 InVals, isThisReturn,
2706 isThisReturn ? OutVals[0] : SDValue(), isCmseNSCall);
2713void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2714 Align Alignment)
const {
2722 unsigned AlignInRegs =
Alignment.value() / 4;
2723 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2724 for (
unsigned i = 0; i < Waste; ++i)
2730 unsigned Excess = 4 * (ARM::R4 -
Reg);
2737 if (NSAAOffset != 0 &&
Size > Excess) {
2749 unsigned ByValRegBegin =
Reg;
2750 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2754 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2760 Size = std::max<int>(
Size - Excess, 0);
2768bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2774 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2775 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2776 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2777 const SelectionDAG &DAG = CLI.
DAG;
2782 assert(Subtarget->supportsTailCall());
2795 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2797 if (!(Subtarget->isThumb1Only() ||
2798 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2799 AddressRegisters.
insert(ARM::R12);
2800 for (
const CCValAssign &AL : ArgLocs)
2802 AddressRegisters.
erase(
AL.getLocReg());
2803 if (AddressRegisters.
empty()) {
2804 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2823 <<
" (guaranteed tail-call CC)\n");
2824 return CalleeCC == CallerCC;
2829 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2831 if (isCalleeStructRet != isCallerStructRet) {
2844 const GlobalValue *GV =
G->getGlobal();
2847 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2848 TT.isOSBinFormatMachO())) {
2865 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2866 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2867 if (CalleeCC != CallerCC) {
2868 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2869 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2878 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2886 const MachineRegisterInfo &MRI = MF.
getRegInfo();
2888 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2907 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2916 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2929 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2932 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2936 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2941 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2963 bool isLittleEndian = Subtarget->isLittle();
2966 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2975 "secure entry function would return value through pointer",
2980 for (
unsigned i = 0, realRVLocIdx = 0;
2982 ++i, ++realRVLocIdx) {
2983 CCValAssign &VA = RVLocs[i];
2986 SDValue Arg = OutVals[realRVLocIdx];
2987 bool ReturnF16 =
false;
2989 if (Subtarget->hasFullFP16() && Subtarget->isTargetHardFloat()) {
3022 auto RetVT = Outs[realRVLocIdx].ArgVT;
3043 SDValue HalfGPRs = DAG.
getNode(ARMISD::VMOVRRD, dl,
3044 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3048 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3054 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3065 SDValue fmrrd = DAG.
getNode(ARMISD::VMOVRRD, dl,
3066 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3068 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3073 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3083 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3109 !Subtarget->isMClass()) {
3110 if (Subtarget->isThumb1Only())
3117 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3120bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3121 if (
N->getNumValues() != 1)
3123 if (!
N->hasNUsesOfValue(1, 0))
3126 SDValue TCChain = Chain;
3127 SDNode *
Copy = *
N->user_begin();
3131 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3133 TCChain =
Copy->getOperand(0);
3134 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3135 SDNode *VMov =
Copy;
3137 SmallPtrSet<SDNode*, 2>
Copies;
3138 for (SDNode *U : VMov->
users()) {
3146 for (SDNode *U : VMov->
users()) {
3147 SDValue UseChain =
U->getOperand(0);
3155 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3163 if (!
Copy->hasOneUse())
3170 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3172 TCChain =
Copy->getOperand(0);
3177 bool HasRet =
false;
3178 for (
const SDNode *U :
Copy->users()) {
3179 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3180 U->getOpcode() != ARMISD::INTRET_GLUE)
3192bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3193 if (!Subtarget->supportsTailCall())
3210 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3226 EVT PtrVT =
Op.getValueType();
3236 if (Subtarget->genExecuteOnly()) {
3241 auto GV =
new GlobalVariable(
3247 return LowerGlobalAddress(GA, DAG);
3253 if (Subtarget->isThumb1Only())
3254 CPAlign = std::max(CPAlign,
Align(4));
3260 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3267 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3276 unsigned ARMPCLabelIndex = 0;
3282 if (!IsPositionIndependent) {
3285 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3292 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3296 if (!IsPositionIndependent)
3298 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex,
DL, MVT::i32);
3299 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3327ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3330 "This function expects a Darwin target");
3335 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3340 SDValue FuncTLVGet = DAG.
getLoad(
3341 MVT::i32,
DL, Chain, DescAddr,
3356 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3362 Chain = DAG.
getCopyToReg(Chain,
DL, ARM::R0, DescAddr, SDValue());
3365 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3371ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3374 "Windows specific TLS lowering");
3381 SDValue
Ops[] = {Chain,
3391 SDValue TEB = CurrentTEB.
getValue(0);
3398 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3406 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3407 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3413 MachinePointerInfo());
3420 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3433 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3435 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3437 ARMConstantPoolValue *CPV =
3445 SDValue Chain =
Argument.getValue(1);
3447 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
3448 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3455 TargetLowering::CallLoweringInfo CLI(DAG);
3460 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3461 return CallResult.first;
3470 const GlobalValue *GV = GA->
getGlobal();
3476 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3480 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3483 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3484 ARMConstantPoolValue *CPV =
3491 PtrVT, dl, Chain,
Offset,
3495 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
3499 PtrVT, dl, Chain,
Offset,
3504 ARMConstantPoolValue *CPV =
3509 PtrVT, dl, Chain,
Offset,
3525 if (
TT.isOSDarwin())
3526 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3528 if (
TT.isOSWindows())
3529 return LowerGlobalTLSAddressWindows(
Op, DAG);
3532 assert(
TT.isOSBinFormatELF() &&
"Only ELF implemented here");
3538 return LowerToTLSGeneralDynamicModel(GA, DAG);
3541 return LowerToTLSExecModels(GA, DAG, model);
3550 while (!Worklist.
empty()) {
3558 if (!
I ||
I->getParent()->getParent() !=
F)
3587 if (!GVar || !GVar->hasInitializer() ||
3588 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3589 !GVar->hasLocalLinkage())
3594 auto *
Init = GVar->getInitializer();
3596 Init->needsDynamicRelocation())
3608 unsigned RequiredPadding = 4 - (
Size % 4);
3609 bool PaddingPossible =
3610 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3615 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3639 if (RequiredPadding != 4) {
3644 while (RequiredPadding--)
3656 ++NumConstpoolPromoted;
3657 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3662 if (!(GV = GA->getAliaseeObject()))
3665 return V->isConstant();
3674 return LowerGlobalAddressWindows(
Op, DAG);
3676 return LowerGlobalAddressELF(
Op, DAG);
3678 return LowerGlobalAddressDarwin(
Op, DAG);
3690 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3703 }
else if (Subtarget->isROPI() && IsRO) {
3708 }
else if (Subtarget->isRWPI() && !IsRO) {
3711 if (Subtarget->useMovt()) {
3714 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3716 ARMConstantPoolValue *CPV =
3719 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3733 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3734 if (Subtarget->useMovt())
3738 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3742 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3751 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3752 "ROPI/RWPI not currently supported for Darwin");
3757 if (Subtarget->useMovt())
3768 if (Subtarget->isGVIndirectSymbol(GV))
3777 "non-Windows COFF is not supported");
3778 assert(Subtarget->useMovt() &&
3779 "Windows on ARM expects to use movw/movt");
3780 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3781 "ROPI/RWPI not currently supported for Windows");
3788 else if (!TM.shouldAssumeDSOLocal(GV))
3811 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3812 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3813 Op.getOperand(1), Val);
3819 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3826 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3830SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3833 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3837 case Intrinsic::arm_gnu_eabi_mcount: {
3841 SDValue Chain =
Op.getOperand(0);
3843 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3844 const uint32_t *
Mask =
3846 assert(Mask &&
"Missing call preserved mask for calling convention");
3849 SDValue ReturnAddress =
3851 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3855 if (Subtarget->isThumb())
3858 ARM::tBL_PUSHLR, dl, ResultTys,
3859 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3860 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3864 {ReturnAddress, Callee, RegisterMask, Chain}),
3873 unsigned IntNo =
Op.getConstantOperandVal(0);
3876 default:
return SDValue();
3877 case Intrinsic::localaddress: {
3879 const auto *RegInfo = Subtarget->getRegisterInfo();
3880 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
3882 Op.getSimpleValueType());
3884 case Intrinsic::eh_recoverfp: {
3885 SDValue FnOp =
Op.getOperand(1);
3890 "llvm.eh.recoverfp must take a function as the first argument");
3891 const auto *RegInfo = Subtarget->getRegisterInfo();
3894 MachineBasicBlock &
MBB = *MF.
begin();
3900 case Intrinsic::thread_pointer: {
3902 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3904 case Intrinsic::arm_cls: {
3908 const SDValue &Operand =
Op.getOperand(1);
3909 const EVT VTy =
Op.getValueType();
3912 case Intrinsic::arm_cls64: {
3918 case Intrinsic::arm_neon_vcls:
3919 case Intrinsic::arm_mve_vcls: {
3922 const EVT VTy =
Op.getValueType();
3925 case Intrinsic::eh_sjlj_lsda: {
3927 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3932 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3933 ARMConstantPoolValue *CPV =
3937 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3942 if (IsPositionIndependent) {
3943 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
3944 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3948 case Intrinsic::arm_neon_vabs:
3951 case Intrinsic::arm_neon_vabds:
3952 if (
Op.getValueType().isInteger())
3954 Op.getOperand(1),
Op.getOperand(2));
3956 case Intrinsic::arm_neon_vabdu:
3958 Op.getOperand(1),
Op.getOperand(2));
3959 case Intrinsic::arm_neon_vmulls:
3960 case Intrinsic::arm_neon_vmullu: {
3961 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3962 ? ARMISD::VMULLs : ARMISD::VMULLu;
3963 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3964 Op.getOperand(1),
Op.getOperand(2));
3966 case Intrinsic::arm_neon_vminnm:
3967 case Intrinsic::arm_neon_vmaxnm: {
3968 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3970 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3971 Op.getOperand(1),
Op.getOperand(2));
3973 case Intrinsic::arm_neon_vminu:
3974 case Intrinsic::arm_neon_vmaxu: {
3975 if (
Op.getValueType().isFloatingPoint())
3977 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3979 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3980 Op.getOperand(1),
Op.getOperand(2));
3982 case Intrinsic::arm_neon_vmins:
3983 case Intrinsic::arm_neon_vmaxs: {
3985 if (!
Op.getValueType().isFloatingPoint()) {
3986 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3988 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3989 Op.getOperand(1),
Op.getOperand(2));
3991 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3993 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3994 Op.getOperand(1),
Op.getOperand(2));
3996 case Intrinsic::arm_neon_vtbl1:
3997 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
3998 Op.getOperand(1),
Op.getOperand(2));
3999 case Intrinsic::arm_neon_vtbl2:
4000 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
4001 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4002 case Intrinsic::arm_mve_pred_i2v:
4003 case Intrinsic::arm_mve_pred_v2i:
4004 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
4006 case Intrinsic::arm_mve_vreinterpretq:
4007 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
4009 case Intrinsic::arm_mve_lsll:
4010 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
4011 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4012 case Intrinsic::arm_mve_asrl:
4013 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
4014 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4015 case Intrinsic::arm_mve_vsli:
4016 return DAG.
getNode(ARMISD::VSLIIMM, SDLoc(
Op),
Op->getVTList(),
4017 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4018 case Intrinsic::arm_mve_vsri:
4019 return DAG.
getNode(ARMISD::VSRIIMM, SDLoc(
Op),
Op->getVTList(),
4020 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4031 if (!Subtarget->hasDataBarrier()) {
4035 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4036 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4037 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
4047 }
else if (Subtarget->preferISHSTBarriers() &&
4056 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4064 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4066 return Op.getOperand(0);
4069 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4071 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4073 return Op.getOperand(0);
4075 unsigned isData =
Op.getConstantOperandVal(4);
4076 if (Subtarget->isThumb()) {
4078 isRead = ~isRead & 1;
4079 isData = ~isData & 1;
4082 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4097 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4105 const SDLoc &dl)
const {
4107 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4111 RC = &ARM::tGPRRegClass;
4113 RC = &ARM::GPRRegClass;
4127 MVT::i32, dl, Root, FIN,
4133 if (!Subtarget->isLittle())
4135 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4148 const Value *OrigArg,
4149 unsigned InRegsParamRecordIdx,
4150 int ArgOffset,
unsigned ArgSize)
const {
4164 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4165 unsigned RBegin, REnd;
4170 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4175 ArgOffset = -4 * (ARM::R4 - RBegin);
4185 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4189 MachinePointerInfo(OrigArg, 4 * i));
4194 if (!MemOps.
empty())
4203 unsigned TotalArgRegsSaveSize,
4204 bool ForceMutable)
const {
4206 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4215 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4219bool ARMTargetLowering::splitValueIntoRegisterParts(
4221 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4223 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4235SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4237 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4238 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4241 SDValue Val = Parts[0];
4251SDValue ARMTargetLowering::LowerFormalArguments(
4258 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4267 unsigned CurArgIdx = 0;
4279 unsigned ArgRegBegin = ARM::R4;
4280 for (
const CCValAssign &VA : ArgLocs) {
4286 if (!
Flags.isByVal())
4290 unsigned RBegin, REnd;
4292 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4298 int lastInsIndex = -1;
4302 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4305 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4309 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4310 CCValAssign &VA = ArgLocs[i];
4311 if (Ins[VA.
getValNo()].isOrigArg()) {
4312 std::advance(CurOrigArg,
4313 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4314 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4325 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4332 MVT::f64, dl, Chain, FIN,
4335 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4343 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4347 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4348 RC = &ARM::HPRRegClass;
4349 else if (RegVT == MVT::f32)
4350 RC = &ARM::SPRRegClass;
4351 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4352 RegVT == MVT::v4bf16)
4353 RC = &ARM::DPRRegClass;
4354 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4355 RegVT == MVT::v8bf16)
4356 RC = &ARM::QPRRegClass;
4357 else if (RegVT == MVT::i32)
4359 : &ARM::GPRRegClass;
4396 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4405 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4411 if (index != lastInsIndex)
4413 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4419 if (
Flags.isByVal()) {
4420 assert(Ins[index].isOrigArg() &&
4421 "Byval arguments cannot be implicit");
4425 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4459 lastInsIndex = index;
4466 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4467 TotalArgRegsSaveSize);
4471 "secure entry function must not be variadic", dl.
getDebugLoc()));
4481 assert(StackAlign &&
"data layout string is missing stack alignment");
4482 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4491 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4500 return CFP->getValueAPF().isPosZero();
4503 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4504 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4507 return CFP->getValueAPF().isPosZero();
4510 Op->getValueType(0) == MVT::f64) {
4514 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4523 if (
Op->getFlags().hasNoSignedWrap())
4539 (isIntEqualitySetCC(CC) ||
4549 if (ST.isThumb1Only() || !
Op.hasOneUse())
4552 unsigned Opc =
Op.getOpcode();
4555 return ShiftAmt->getZExtValue() <= 31 ? 1 : 0;
4558 return ST.isThumb() ? 0 : 1;
4566 return ST.isThumb() ? 0 : 1;
4576 const SDLoc &dl)
const {
4578 unsigned C = RHSC->getZExtValue();
4636 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4640 unsigned Mask =
LHS.getConstantOperandVal(1);
4642 uint64_t RHSV = RHSC->getZExtValue();
4643 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4645 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4646 SDValue ShiftAmt = DAG.
getConstant(ShiftBits, dl, MVT::i32);
4659 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4662 LHS.getConstantOperandVal(1) < 31) {
4663 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4673 unsigned CompareType;
4676 CompareType = ARMISD::CMP;
4681 CompareType = ARMISD::CMPZ;
4690 if (CompareType != ARMISD::CMPZ &&
isCMN(
RHS, CC, DAG)) {
4691 CompareType = ARMISD::CMN;
4693 }
else if (CompareType != ARMISD::CMPZ &&
isCMN(
LHS, CC, DAG)) {
4694 CompareType = ARMISD::CMN;
4708 if (CompareType == ARMISD::CMP)
4736 bool Signaling)
const {
4737 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4743 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4752std::pair<SDValue, SDValue>
4755 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4757 SDValue
Value, OverflowCmp;
4758 SDValue
LHS =
Op.getOperand(0);
4759 SDValue
RHS =
Op.getOperand(1);
4767 switch (
Op.getOpcode()) {
4819 return std::make_pair(
Value, OverflowCmp);
4832 return Cmp.getValue(1);
4860 return DAG.
getNode(ARMISD::CMOV,
DL, VT, Zero, One, ARMcc, Flags);
4868 SDValue
LHS =
Op.getOperand(0);
4869 SDValue
RHS =
Op.getOperand(1);
4872 EVT VT =
Op.getValueType();
4873 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4876 switch (
Op.getOpcode()) {
4889 SDValue OverflowCmp, ARMcc;
4890 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4896 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4899 ARMcc, OverflowCmp);
4909 EVT VT =
Op.getValueType();
4910 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4920 switch (
Op->getOpcode()) {
4922 NewOpcode = ARMISD::UQADD8b;
4925 NewOpcode = ARMISD::QADD8b;
4928 NewOpcode = ARMISD::UQSUB8b;
4931 NewOpcode = ARMISD::QSUB8b;
4936 switch (
Op->getOpcode()) {
4938 NewOpcode = ARMISD::UQADD16b;
4941 NewOpcode = ARMISD::QADD16b;
4944 NewOpcode = ARMISD::UQSUB16b;
4947 NewOpcode = ARMISD::QSUB16b;
4955 DAG.
getNode(NewOpcode, dl, MVT::i32,
4962 SDValue
Cond =
Op.getOperand(0);
4963 SDValue SelectTrue =
Op.getOperand(1);
4964 SDValue SelectFalse =
Op.getOperand(2);
4966 unsigned Opc =
Cond.getOpcode();
4968 if (
Cond.getResNo() == 1 &&
4974 SDValue
Value, OverflowCmp;
4976 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4977 EVT VT =
Op.getValueType();
4979 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4987 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4988 const ConstantSDNode *CMOVTrue =
4990 const ConstantSDNode *CMOVFalse =
4993 if (CMOVTrue && CMOVFalse) {
4999 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5001 False = SelectFalse;
5002 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5008 return getCMOV(dl,
Op.getValueType(),
True,
False,
Cond.getOperand(2),
5009 Cond.getOperand(3), DAG);
5019 bool &swpCmpOps,
bool &swpVselOps) {
5047 swpCmpOps = !swpCmpOps;
5048 swpVselOps = !swpVselOps;
5071 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5073 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5075 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5077 SDValue TrueLow =
TrueVal.getValue(0);
5078 SDValue TrueHigh =
TrueVal.getValue(1);
5079 SDValue FalseLow =
FalseVal.getValue(0);
5080 SDValue FalseHigh =
FalseVal.getValue(1);
5082 SDValue
Low = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, FalseLow, TrueLow,
5084 SDValue
High = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, FalseHigh, TrueHigh,
5089 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5110 ((
K ==
LHS &&
K == TrueVal) || (
K ==
RHS &&
K == FalseVal))) ||
5112 ((
K ==
RHS &&
K == TrueVal) || (
K ==
LHS &&
K == FalseVal)));
5133 EVT VT =
Op.getValueType();
5155 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5168 int64_t PosVal = std::max(Val1, Val2);
5169 int64_t NegVal = std::min(Val1, Val2);
5181 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5184 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5216 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5221 if (*
K != KTmp || V != VTmp)
5232bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5234 return !Subtarget->hasVFP2Base();
5236 return !Subtarget->hasFP64();
5238 return !Subtarget->hasFullFP16();
5246 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5254 if (TVal == ~FVal) {
5255 Opcode = ARMISD::CSINV;
5256 }
else if (TVal == ~FVal + 1) {
5257 Opcode = ARMISD::CSNEG;
5258 }
else if (TVal + 1 == FVal) {
5259 Opcode = ARMISD::CSINC;
5260 }
else if (TVal == FVal + 1) {
5261 Opcode = ARMISD::CSINC;
5264 InvertCond = !InvertCond;
5271 if (Opcode != ARMISD::CSINC &&
5275 InvertCond = !InvertCond;
5281 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5284 InvertCond = !InvertCond;
5291 EVT VT =
Op.getValueType();
5295 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5305 SDValue LowerSatConstant;
5307 if (VT == MVT::i32 &&
5319 SDValue
LHS =
Op.getOperand(0);
5320 SDValue
RHS =
Op.getOperand(1);
5326 if (
Op.getValueType().isInteger()) {
5334 LHS.getValueType() ==
RHS.getValueType()) {
5335 EVT VT =
LHS.getValueType();
5341 Shift = DAG.
getNOT(dl, Shift, VT);
5353 if (
LHS.getValueType() == MVT::i32) {
5357 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5362 SDValue
Cmp = getARMCmp(
LHS,
RHS, CC, ARMcc, DAG, dl);
5363 EVT VT =
Op.getValueType();
5364 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5368 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5373 if (!
RHS.getNode()) {
5379 if (
LHS.getValueType() == MVT::i32) {
5390 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5391 TrueVal.getValueType() == MVT::f32 ||
5392 TrueVal.getValueType() == MVT::f64)) {
5402 SDValue
Cmp = getARMCmp(
LHS,
RHS, CC, ARMcc, DAG, dl);
5406 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5416 if (Subtarget->hasFPARMv8Base() &&
5418 (
TrueVal.getValueType() == MVT::f16 ||
5419 TrueVal.getValueType() == MVT::f32 ||
5420 TrueVal.getValueType() == MVT::f64)) {
5421 bool swpCmpOps =
false;
5422 bool swpVselOps =
false;
5434 SDValue ARMcc = DAG.
getConstant(CondCode, dl, MVT::i32);
5435 SDValue
Cmp = getVFPCmp(
LHS,
RHS, DAG, dl);
5436 SDValue
Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5438 SDValue ARMcc2 = DAG.
getConstant(CondCode2, dl, MVT::i32);
5439 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5449 if (!
N->hasOneUse())
5452 if (!
N->getNumValues())
5454 EVT VT =
Op.getValueType();
5455 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5472 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5473 Ld->getPointerInfo(), Ld->getAlign(),
5474 Ld->getMemOperand()->getFlags());
5490 SDValue Ptr = Ld->getBasePtr();
5492 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5493 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5498 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5499 Ld->getPointerInfo().getWithOffset(4),
5501 Ld->getMemOperand()->getFlags());
5512 SDValue Chain =
Op.getOperand(0);
5514 SDValue
LHS =
Op.getOperand(2);
5515 SDValue
RHS =
Op.getOperand(3);
5516 SDValue Dest =
Op.getOperand(4);
5519 bool LHSSeenZero =
false;
5521 bool RHSSeenZero =
false;
5523 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5534 if (
LHS.getValueType() == MVT::f32) {
5539 SDValue
Cmp = getARMCmp(
LHS,
RHS, CC, ARMcc, DAG, dl);
5540 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5552 SDValue
Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5553 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5568 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5580 SDValue Chain =
Op.getOperand(0);
5581 SDValue
Cond =
Op.getOperand(1);
5582 SDValue Dest =
Op.getOperand(2);
5587 unsigned Opc =
Cond.getOpcode();
5589 !Subtarget->isThumb1Only();
5590 if (
Cond.getResNo() == 1 &&
5598 SDValue
Value, OverflowCmp;
5600 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5605 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5613 SDValue Chain =
Op.getOperand(0);
5615 SDValue
LHS =
Op.getOperand(2);
5616 SDValue
RHS =
Op.getOperand(3);
5617 SDValue Dest =
Op.getOperand(4);
5620 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5625 if (!
RHS.getNode()) {
5633 unsigned Opc =
LHS.getOpcode();
5635 !Subtarget->isThumb1Only();
5645 SDValue
Value, OverflowCmp;
5647 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5654 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5658 if (
LHS.getValueType() == MVT::i32) {
5660 SDValue
Cmp = getARMCmp(
LHS,
RHS, CC, ARMcc, DAG, dl);
5661 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5664 SDNodeFlags
Flags =
Op->getFlags();
5665 if (
Flags.hasNoNaNs() &&
5670 if (SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5677 SDValue ARMcc = DAG.
getConstant(CondCode, dl, MVT::i32);
5678 SDValue
Cmp = getVFPCmp(
LHS,
RHS, DAG, dl);
5679 SDValue
Ops[] = {Chain, Dest, ARMcc,
Cmp};
5680 SDValue Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5683 SDValue
Ops[] = {Res, Dest, ARMcc,
Cmp};
5684 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5690 SDValue Chain =
Op.getOperand(0);
5691 SDValue
Table =
Op.getOperand(1);
5692 SDValue
Index =
Op.getOperand(2);
5698 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5701 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5706 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5707 Addr,
Op.getOperand(2), JTI);
5711 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5715 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5718 DAG.
getLoad(PTy, dl, Chain, Addr,
5721 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5726 EVT VT =
Op.getValueType();
5729 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5730 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5738 const EVT OpTy =
Op.getOperand(0).getValueType();
5739 if (
OpTy == MVT::v4f32)
5741 else if (
OpTy == MVT::v4f16 && HasFullFP16)
5743 else if (
OpTy == MVT::v8f16 && HasFullFP16)
5748 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5751 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5756 EVT VT =
Op.getValueType();
5760 bool IsStrict =
Op->isStrictFPOpcode();
5761 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5763 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5774 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
5776 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5777 CallOptions, Loc, Chain);
5786 EVT VT =
Op.getValueType();
5788 EVT FromVT =
Op.getOperand(0).getValueType();
5790 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5792 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5793 Subtarget->hasFP64())
5795 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5796 Subtarget->hasFullFP16())
5798 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5799 Subtarget->hasMVEFloatOps())
5801 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5802 Subtarget->hasMVEFloatOps())
5805 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5822 EVT VT =
Op.getValueType();
5825 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5831 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5832 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5833 "Invalid type for custom lowering!");
5838 if (VT == MVT::v4f32)
5839 DestVecType = MVT::v4i32;
5840 else if (VT == MVT::v4f16 && HasFullFP16)
5841 DestVecType = MVT::v4i16;
5842 else if (VT == MVT::v8f16 && HasFullFP16)
5843 DestVecType = MVT::v8i16;
5849 switch (
Op.getOpcode()) {
5861 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5866 EVT VT =
Op.getValueType();
5870 bool IsStrict =
Op->isStrictFPOpcode();
5871 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5873 if (isUnsupportedFloatingType(VT)) {
5882 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
5884 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5885 CallOptions, Loc, Chain);
5894 SDValue Tmp0 =
Op.getOperand(0);
5895 SDValue Tmp1 =
Op.getOperand(1);
5897 EVT VT =
Op.getValueType();
5901 bool UseNEON = !InGPR && Subtarget->hasNEON();
5906 SDValue
Mask = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v2i32,
5908 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5915 if (SrcVT == MVT::f32) {
5918 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5921 }
else if (VT == MVT::f32)
5922 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5937 if (VT == MVT::f32) {
5949 if (SrcVT == MVT::f64)
5955 SDValue Mask1 = DAG.
getConstant(0x80000000, dl, MVT::i32);
5956 SDValue Mask2 = DAG.
getConstant(0x7fffffff, dl, MVT::i32);
5958 if (VT == MVT::f32) {
5971 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5979 EVT VT =
Op.getValueType();
5981 unsigned Depth =
Op.getConstantOperandVal(0);
5983 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5987 MachinePointerInfo());
5996 const ARMBaseRegisterInfo &ARI =
5997 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
6002 EVT VT =
Op.getValueType();
6004 unsigned Depth =
Op.getConstantOperandVal(0);
6009 MachinePointerInfo());
6017 return StringSwitch<Register>(
RegName)
6018 .Case(
"sp", ARM::SP)
6029 assert(
N->getValueType(0) == MVT::i64
6030 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6033 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6073 const APInt &APIntIndex = Index->getAPIntValue();
6075 NewIndex *= APIntIndex;
6100 SDValue
Op =
N->getOperand(0);
6104 EVT SrcVT =
Op.getValueType();
6105 EVT DstVT =
N->getValueType(0);
6107 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6108 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6109 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6112 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6113 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6114 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6121 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6133 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6141 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6143 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6145 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6165 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6174 EVT VT =
Op.getValueType();
6177 SDValue ShOpLo =
Op.getOperand(0);
6178 SDValue ShOpHi =
Op.getOperand(1);
6179 SDValue ShAmt =
Op.getOperand(2);
6192 SDValue LoBigShift = DAG.
getNode(
Opc, dl, VT, ShOpHi, ExtraShAmt);
6193 SDValue CmpLo = getARMCmp(ExtraShAmt, DAG.
getConstant(0, dl, MVT::i32),
6196 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6198 SDValue HiSmallShift = DAG.
getNode(
Opc, dl, VT, ShOpHi, ShAmt);
6203 SDValue CmpHi = getARMCmp(ExtraShAmt, DAG.
getConstant(0, dl, MVT::i32),
6206 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6217 EVT VT =
Op.getValueType();
6220 SDValue ShOpLo =
Op.getOperand(0);
6221 SDValue ShOpHi =
Op.getOperand(1);
6222 SDValue ShAmt =
Op.getOperand(2);
6234 SDValue HiBigShift = DAG.
getNode(
ISD::SHL, dl, VT, ShOpLo, ExtraShAmt);
6235 SDValue CmpHi = getARMCmp(ExtraShAmt, DAG.
getConstant(0, dl, MVT::i32),
6238 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6240 SDValue CmpLo = getARMCmp(ExtraShAmt, DAG.
getConstant(0, dl, MVT::i32),
6243 SDValue
Lo = DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift,
6257 SDValue Chain =
Op.getOperand(0);
6258 SDValue
Ops[] = {Chain,
6259 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6276 SDValue Chain =
Op->getOperand(0);
6277 SDValue RMValue =
Op->getOperand(1);
6298 SDValue
Ops[] = {Chain,
6311 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6318 SDValue Chain =
Op->getOperand(0);
6319 SDValue
Mode =
Op->getOperand(1);
6323 SDValue
Ops[] = {Chain,
6330 SDValue FPSCRMasked =
6333 SDValue InputMasked =
6339 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6346 SDValue Chain =
Op->getOperand(0);
6350 SDValue
Ops[] = {Chain,
6357 SDValue FPSCRMasked = DAG.
getNode(
6360 SDValue Ops2[] = {Chain,
6369 EVT VT =
N->getValueType(0);
6370 if (VT.
isVector() && ST->hasNEON()) {
6390 unsigned NumBits =
ElemTy.getSizeInBits();
6392 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6402 if (
ElemTy == MVT::i64) {
6415 if (!ST->hasV6T2Ops())
6424 EVT VT =
N->getValueType(0);
6427 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6428 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6429 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6430 "Unexpected type for custom ctpop lowering");
6438 unsigned EltSize = 8;
6461 Op =
Op.getOperand(0);
6463 APInt SplatBits, SplatUndef;
6464 unsigned SplatBitSize;
6467 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6469 SplatBitSize > ElementBits)
6480 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6484 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6495 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6500 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6501 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6510 EVT VT =
N->getValueType(0);
6525 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6527 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6532 "unexpected vector shift opcode");
6534 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6535 unsigned VShiftOpc =
6536 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6537 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6543 EVT ShiftVT =
N->getOperand(1).getValueType();
6546 unsigned VShiftOpc =
6547 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6548 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6553 EVT VT =
N->getValueType(0);
6562 "Unknown shift to lower!");
6564 unsigned ShOpc =
N->getOpcode();
6565 if (ST->hasMVEIntegerOps()) {
6567 unsigned ShPartsOpc = ARMISD::LSLL;
6588 ShPartsOpc = ARMISD::LSRL;
6590 ShPartsOpc = ARMISD::ASRL;
6595 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6609 if (ST->isThumb1Only())
6614 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6618 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6622 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6630 bool Invert =
false;
6637 EVT VT =
Op.getValueType();
6645 assert(ST->hasMVEIntegerOps() &&
6646 "No hardware support for integer vector comparison!");
6648 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6669 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6673 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6683 switch (SetCCOpcode) {
6687 if (ST->hasMVEFloatOps()) {
6690 Invert =
true; [[fallthrough]];
6715 Result = DAG.
getNOT(dl, Result, VT);
6718 case ISD::SETUO: Invert =
true; [[fallthrough]];
6727 Result = DAG.
getNOT(dl, Result, VT);
6733 switch (SetCCOpcode) {
6736 if (ST->hasMVEIntegerOps()) {
6739 Invert =
true; [[fallthrough]];
6761 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6764 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6769 Result = DAG.
getNOT(dl, Result, VT);
6794 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6797 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6803 Result = DAG.
getNOT(dl, Result, VT);
6812 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6829 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6840 unsigned OpCmode,
Imm;
6851 switch (SplatBitSize) {
6856 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6859 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6864 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6865 if ((SplatBits & ~0xff) == 0) {
6871 if ((SplatBits & ~0xff00) == 0) {
6874 Imm = SplatBits >> 8;
6884 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6885 if ((SplatBits & ~0xff) == 0) {
6891 if ((SplatBits & ~0xff00) == 0) {
6894 Imm = SplatBits >> 8;
6897 if ((SplatBits & ~0xff0000) == 0) {
6900 Imm = SplatBits >> 16;
6903 if ((SplatBits & ~0xff000000) == 0) {
6906 Imm = SplatBits >> 24;
6913 if ((SplatBits & ~0xffff) == 0 &&
6914 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6917 Imm = SplatBits >> 8;
6925 if ((SplatBits & ~0xffffff) == 0 &&
6926 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6929 Imm = SplatBits >> 16;
6945 unsigned ImmMask = 1;
6947 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6948 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6950 }
else if ((SplatBits & BitMask) != 0) {
6959 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6973 EVT VT =
Op.getValueType();
6974 bool IsDouble = (VT == MVT::f64);
6980 if (
ST->genExecuteOnly()) {
6982 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6983 "Unexpected architecture");
7001 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
7006 if (!
ST->hasVFP3Base())
7011 if (IsDouble && !Subtarget->hasFP64())
7018 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7028 SDValue VecConstant = DAG.
getNode(ARMISD::VMOVFPIMM,
DL, MVT::v2f32,
7036 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7045 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7051 if (NewVal != SDValue()) {
7053 SDValue VecConstant = DAG.
getNode(ARMISD::VMOVIMM,
DL, VMovVT,
7068 if (NewVal != SDValue()) {
7070 SDValue VecConstant = DAG.
getNode(ARMISD::VMVNIMM,
DL, VMovVT, NewVal);
7099 unsigned ExpectedElt =
Imm;
7100 for (
unsigned i = 1; i < NumElts; ++i) {
7104 if (ExpectedElt == NumElts)
7107 if (M[i] < 0)
continue;
7108 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7116 bool &ReverseVEXT,
unsigned &
Imm) {
7118 ReverseVEXT =
false;
7129 unsigned ExpectedElt =
Imm;
7130 for (
unsigned i = 1; i < NumElts; ++i) {
7134 if (ExpectedElt == NumElts * 2) {
7139 if (M[i] < 0)
continue;
7140 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7155 return VT == MVT::v8i8 && M.size() == 8;
7161 unsigned &WhichResult,
7164 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7165 return ARMISD::VTRN;
7166 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7167 return ARMISD::VUZP;
7168 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7169 return ARMISD::VZIP;
7173 return ARMISD::VTRN;
7175 return ARMISD::VUZP;
7177 return ARMISD::VZIP;
7186 if (NumElts != M.size())
7190 for (
unsigned i = 0; i != NumElts; ++i)
7191 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7200 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7208 int Ofs = Top ? 1 : 0;
7209 int Upper = SingleSource ? 0 : NumElts;
7210 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7211 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7213 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7222 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7231 unsigned Offset = Top ? 0 : 1;
7232 unsigned N = SingleSource ? 0 : NumElts;
7233 for (
unsigned i = 0; i < NumElts; i += 2) {
7234 if (M[i] >= 0 && M[i] != (
int)i)
7236 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7245 if (NumElts != M.size())
7253 unsigned Off0 = rev ? NumElts / 2 : 0;
7254 unsigned Off1 = rev ? 0 : NumElts / 2;
7255 for (
unsigned i = 0; i < NumElts; i += 2) {
7256 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7258 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7274 if (!ST->hasMVEFloatOps())
7279 if (VT != MVT::v8f16)
7300 for (
unsigned i = 1; i < 4; i++) {
7315 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7327 if (!ST->hasMVEFloatOps())
7332 if (VT != MVT::v4f32)
7348 for (
unsigned i = 1; i < 4; i++) {
7359 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7371 Val =
N->getAsZExtVal();
7373 if (ST->isThumb1Only()) {
7374 if (Val <= 255 || ~Val <= 255)
7386 EVT VT =
Op.getValueType();
7388 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7392 unsigned BitsPerBool;
7396 }
else if (NumElts == 4) {
7399 }
else if (NumElts == 8) {
7402 }
else if (NumElts == 16) {
7413 return U.get().isUndef() || U.get() == FirstOp;
7417 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7421 unsigned Bits32 = 0;
7422 for (
unsigned i = 0; i < NumElts; ++i) {
7426 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7428 Bits32 |= BoolMask << (i * BitsPerBool);
7434 for (
unsigned i = 0; i < NumElts; ++i) {
7447 if (!ST->hasMVEIntegerOps())
7451 EVT VT =
Op.getValueType();
7461 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7465 for (
unsigned I = 2;
I < NumElts;
I++) {
7481 switch (
N->getOpcode()) {
7492 return N->getOperand(1).getNode() ==
Op;
7494 switch (
N->getConstantOperandVal(0)) {
7495 case Intrinsic::arm_mve_add_predicated:
7496 case Intrinsic::arm_mve_mul_predicated:
7497 case Intrinsic::arm_mve_qadd_predicated:
7498 case Intrinsic::arm_mve_vhadd:
7499 case Intrinsic::arm_mve_hadd_predicated:
7500 case Intrinsic::arm_mve_vqdmulh:
7501 case Intrinsic::arm_mve_qdmulh_predicated:
7502 case Intrinsic::arm_mve_vqrdmulh:
7503 case Intrinsic::arm_mve_qrdmulh_predicated:
7504 case Intrinsic::arm_mve_vqdmull:
7505 case Intrinsic::arm_mve_vqdmull_predicated:
7507 case Intrinsic::arm_mve_sub_predicated:
7508 case Intrinsic::arm_mve_qsub_predicated:
7509 case Intrinsic::arm_mve_vhsub:
7510 case Intrinsic::arm_mve_hsub_predicated:
7511 return N->getOperand(2).getNode() ==
Op;
7526 EVT VT =
Op.getValueType();
7534 APInt SplatBits, SplatUndef;
7535 unsigned SplatBitSize;
7537 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7544 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7546 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7547 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7548 : SplatBitSize == 16 ? MVT::v8i16
7551 SDValue VDup = DAG.
getNode(ARMISD::VDUP, dl, DupVT, Const);
7552 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7555 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7556 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7561 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7564 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, Val);
7565 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7569 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7571 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7574 SDValue Vmov = DAG.
getNode(ARMISD::VMVNIMM, dl, VmovVT, Val);
7575 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7579 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7583 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7589 if (
ST->hasMVEIntegerOps() &&
7590 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7591 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7592 : SplatBitSize == 16 ? MVT::v8i16
7595 SDValue VDup = DAG.
getNode(ARMISD::VDUP, dl, DupVT, Const);
7596 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7609 bool isOnlyLowElement =
true;
7610 bool usesOnlyOneValue =
true;
7611 bool hasDominantValue =
false;
7616 DenseMap<SDValue, unsigned> ValueCounts;
7618 for (
unsigned i = 0; i < NumElts; ++i) {
7619 SDValue
V =
Op.getOperand(i);
7623 isOnlyLowElement =
false;
7627 unsigned &
Count = ValueCounts[
V];
7630 if (++
Count > (NumElts / 2)) {
7631 hasDominantValue =
true;
7635 if (ValueCounts.
size() != 1)
7636 usesOnlyOneValue =
false;
7637 if (!
Value.getNode() && !ValueCounts.
empty())
7640 if (ValueCounts.
empty())
7646 (VT != MVT::v8f16 ||
ST->hasFullFP16()))
7653 if (hasDominantValue && EltSize <= 32) {
7662 ConstantSDNode *constIndex;
7669 if (VT !=
Value->getOperand(0).getValueType()) {
7672 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7677 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7682 if (!usesOnlyOneValue) {
7685 for (
unsigned I = 0;
I < NumElts; ++
I) {
7690 Ops.push_back(
Op.getOperand(
I));
7700 assert(FVT == MVT::f32 || FVT == MVT::f16);
7701 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7702 for (
unsigned i = 0; i < NumElts; ++i)
7707 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7711 if (usesOnlyOneValue) {
7714 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7728 if (SDValue
shuffle = ReconstructShuffle(
Op, DAG))
7738 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7758 if (EltSize >= 32) {
7764 for (
unsigned i = 0; i < NumElts; ++i)
7777 (VT == MVT::v8f16 && !
ST->hasFullFP16())) {
7779 for (
unsigned i = 0 ; i < NumElts; ++i) {
7780 SDValue
V =
Op.getOperand(i);
7783 SDValue LaneIdx = DAG.
getConstant(i, dl, MVT::i32);
7798 EVT VT =
Op.getValueType();
7801 struct ShuffleSourceInfo {
7803 unsigned MinElt = std::numeric_limits<unsigned>::max();
7804 unsigned MaxElt = 0;
7814 int WindowScale = 1;
7816 ShuffleSourceInfo(SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7818 bool operator ==(SDValue OtherVec) {
return Vec == OtherVec; }
7824 for (
unsigned i = 0; i < NumElts; ++i) {
7825 SDValue
V =
Op.getOperand(i);
7839 SDValue SourceVec =
V.getOperand(0);
7841 if (Source == Sources.
end())
7845 unsigned EltNo =
V.getConstantOperandVal(1);
7852 if (Sources.
size() > 2)
7858 for (
auto &Source : Sources) {
7859 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
7860 if (SrcEltTy.
bitsLT(SmallestEltTy))
7861 SmallestEltTy = SrcEltTy;
7863 unsigned ResMultiplier =
7871 for (
auto &Src : Sources) {
7872 EVT SrcVT = Src.ShuffleVec.getValueType();
7876 if (SrcVTSize == VTSize)
7885 if (SrcVTSize < VTSize) {
7886 if (2 * SrcVTSize != VTSize)
7892 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
7896 if (SrcVTSize != 2 * VTSize)
7899 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
7904 if (Src.MinElt >= NumSrcElts) {
7909 Src.WindowBase = -NumSrcElts;
7910 }
else if (Src.MaxElt < NumSrcElts) {
7924 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
7927 Src.WindowBase = -Src.MinElt;
7934 for (
auto &Src : Sources) {
7935 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
7936 if (SrcEltTy == SmallestEltTy)
7939 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
7941 Src.WindowBase *= Src.WindowScale;
7946 for (
auto Src : Sources)
7947 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
7954 SDValue
Entry =
Op.getOperand(i);
7955 if (
Entry.isUndef())
7964 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
7967 int LanesDefined = BitsDefined / BitsPerShuffleLane;
7971 int *LaneMask = &
Mask[i * ResMultiplier];
7973 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
7974 ExtractBase += NumElts * (Src - Sources.begin());
7975 for (
int j = 0;
j < LanesDefined; ++
j)
7976 LaneMask[j] = ExtractBase + j;
7982 assert(Sources.size() <= 2 &&
"Too many sources!");
7985 for (
unsigned i = 0; i < Sources.size(); ++i)
7992 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8014 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8034 unsigned PFIndexes[4];
8035 for (
unsigned i = 0; i != 4; ++i) {
8039 PFIndexes[i] = M[i];
8043 unsigned PFTableIndex =
8044 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8046 unsigned Cost = (PFEntry >> 30);
8052 bool ReverseVEXT, isV_UNDEF;
8053 unsigned Imm, WhichResult;
8056 if (EltSize >= 32 ||
8063 else if (Subtarget->hasNEON() &&
8068 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8071 else if (Subtarget->hasMVEIntegerOps() &&
8075 else if (Subtarget->hasMVEIntegerOps() &&
8089 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8090 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8091 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8094 if (LHSID == (1*9+2)*9+3)
return LHS;
8095 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8109 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8112 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8115 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8120 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8125 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8152 for (
int I : ShuffleMask)
8156 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8,
V1,
8159 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8,
V1, V2,
8165 EVT VT =
Op.getValueType();
8167 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8168 "Expect an v8i16/v16i8 type");
8174 std::vector<int> NewMask;
8178 NewMask.push_back(i);
8208 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8218 if (VT != MVT::v16i1)
8219 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8234 EVT VT =
Op.getValueType();
8238 assert(ST->hasMVEIntegerOps() &&
8239 "No support for vector shuffle of boolean predicates");
8249 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8265 "Expected identical vector type in expanded i1 shuffle!");
8269 PredAsVector2, ShuffleMask);
8274 if (VT == MVT::v2i1) {
8275 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8278 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8280 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8291 EVT VT =
Op.getValueType();
8295 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8296 "Unexpected vector type");
8298 int QuarterSize = NumElts / 4;
8307 for (
int i = 0; i <
Length; i++) {
8308 if (ShuffleMask[Start + i] >= 0) {
8309 if (ShuffleMask[Start + i] %
Length != i)
8311 MovIdx = ShuffleMask[Start + i] /
Length;
8319 for (
int i = 1; i <
Length; i++) {
8320 if (ShuffleMask[Start + i] >= 0 &&
8321 (ShuffleMask[Start + i] /
Length != MovIdx ||
8322 ShuffleMask[Start + i] %
Length != i))
8328 for (
int Part = 0; Part < 4; ++Part) {
8330 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8344 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8349 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8351 for (
int Part = 0; Part < 4; ++Part)
8352 for (
int i = 0; i < QuarterSize; i++)
8354 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8356 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8359 for (
int Part = 0; Part < 4; ++Part)
8375 EVT VT =
Op.getValueType();
8387 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8391 if (Mask[i] != i + BaseOffset) {
8392 if (OffElement == -1)
8398 return NonUndef > 2 && OffElement != -1;
8402 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8404 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8415 ShuffleMask[OffElement] < (
int)NumElts ?
V1 : V2,
8426 EVT VT =
Op.getValueType();
8430 if (ST->hasMVEIntegerOps() && EltSize == 1)
8441 if (EltSize <= 32) {
8445 if (Lane == -1) Lane = 0;
8449 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8456 bool IsScalarToVector =
true;
8457 for (
unsigned i = 1, e =
V1.getNumOperands(); i != e; ++i)
8458 if (!
V1.getOperand(i).isUndef()) {
8459 IsScalarToVector =
false;
8462 if (IsScalarToVector)
8463 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8465 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
V1,
8469 bool ReverseVEXT =
false;
8471 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT,
Imm)) {
8474 return DAG.
getNode(ARMISD::VEXT, dl, VT,
V1, V2,
8479 return DAG.
getNode(ARMISD::VREV64, dl, VT,
V1);
8481 return DAG.
getNode(ARMISD::VREV32, dl, VT,
V1);
8483 return DAG.
getNode(ARMISD::VREV16, dl, VT,
V1);
8495 unsigned WhichResult = 0;
8496 bool isV_UNDEF =
false;
8497 if (ST->hasNEON()) {
8499 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8506 if (ST->hasMVEIntegerOps()) {
8508 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2,
V1,
8511 return DAG.
getNode(ARMISD::VMOVN, dl, VT,
V1, V2,
8541 }) &&
"Unexpected shuffle index into UNDEF operand!");
8544 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8547 assert((WhichResult == 0) &&
8548 "In-place shuffle of concat can only have one result!");
8557 if (ST->hasMVEIntegerOps() && EltSize <= 32 &&
8558 (ST->hasFullFP16() || VT != MVT::v8f16)) {
8562 for (
bool Top : {
false,
true}) {
8563 for (
bool SingleSource : {
false,
true}) {
8564 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8569 SingleSource ?
V1 : V2);
8585 unsigned PFIndexes[4];
8586 for (
unsigned i = 0; i != 4; ++i) {
8587 if (ShuffleMask[i] < 0)
8590 PFIndexes[i] = ShuffleMask[i];
8594 unsigned PFTableIndex =
8595 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8597 unsigned Cost = (PFEntry >> 30);
8603 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8604 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8614 if (EltSize >= 32) {
8622 for (
unsigned i = 0; i < NumElts; ++i) {
8623 if (ShuffleMask[i] < 0)
8627 ShuffleMask[i] < (
int)NumElts ?
V1 : V2,
8635 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8639 if (ST->hasNEON() && VT == MVT::v8i8)
8643 if (ST->hasMVEIntegerOps())
8648 if (VT == MVT::v8f16 && !ST->hasFullFP16()) {
8650 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(0));
8652 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(1));
8654 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuf);
8662 EVT VecVT =
Op.getOperand(0).getValueType();
8665 assert(ST->hasMVEIntegerOps() &&
8666 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8669 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8670 unsigned Lane =
Op.getConstantOperandVal(2);
8671 unsigned LaneWidth =
8673 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8678 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8684 SDValue Lane =
Op.getOperand(2);
8688 SDValue Elt =
Op.getOperand(1);
8691 if (Subtarget->hasMVEIntegerOps() &&
8692 Op.getValueType().getScalarSizeInBits() == 1)
8708 SDValue VecIn =
Op.getOperand(0);
8716 IVecIn, IElt, Lane);
8725 EVT VecVT =
Op.getOperand(0).getValueType();
8728 assert(ST->hasMVEIntegerOps() &&
8729 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8732 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8733 unsigned Lane =
Op.getConstantOperandVal(1);
8734 unsigned LaneWidth =
8756 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8765 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8766 "Unexpected custom CONCAT_VECTORS lowering");
8768 "Unexpected custom CONCAT_VECTORS lowering");
8769 assert(ST->hasMVEIntegerOps() &&
8770 "CONCAT_VECTORS lowering only supported for MVE");
8773 EVT Op1VT =
V1.getValueType();
8774 EVT Op2VT = V2.getValueType();
8775 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8776 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8777 "Unexpected i1 concat operations!");
8790 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8795 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8804 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8805 EVT NewVT = NewV.getValueType();
8806 EVT ConcatVT = ConVec.getValueType();
8807 unsigned ExtScale = 1;
8808 if (NewVT == MVT::v2f64) {
8809 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8822 ConVec = ExtractInto(NewV1, ConVec, j);
8823 ConVec = ExtractInto(NewV2, ConVec, j);
8827 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8833 while (ConcatOps.
size() > 1) {
8834 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8837 ConcatOps[
I / 2] = ConcatPair(
V1, V2);
8841 return ConcatOps[0];
8846 EVT VT =
Op->getValueType(0);
8852 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
8853 "unexpected CONCAT_VECTORS");
8874 EVT VT =
Op.getValueType();
8875 EVT Op1VT =
V1.getValueType();
8880 "Unexpected custom EXTRACT_SUBVECTOR lowering");
8881 assert(ST->hasMVEIntegerOps() &&
8882 "EXTRACT_SUBVECTOR lowering only supported for MVE");
8892 EVT SubVT = MVT::v4i32;
8894 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
8904 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8909 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
8918 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
8925 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
8926 EVT VT =
N->getValueType(0);
8927 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
8928 "Expected a vector i1 type!");
8930 EVT FromVT =
Op.getValueType();
8941 if (!Subtarget->hasMVEIntegerOps())
8944 EVT ToVT =
N->getValueType(0);
8987 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
8989 EVT FromVT =
N->getOperand(0).getValueType();
8990 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9001 if (!Subtarget->hasMVEIntegerOps())
9006 EVT ToVT =
N->getValueType(0);
9007 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9010 EVT FromVT =
Op.getValueType();
9011 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9025 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9026 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9038 EVT VT =
N->getValueType(0);
9040 SDNode *BVN =
N->getOperand(0).getNode();
9045 unsigned HiElt = 1 - LoElt;
9050 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9066 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9067 SDNode *Elt =
N->getOperand(i).getNode();
9070 unsigned HalfSize = EltSize / 2;
9072 if (!
isIntN(HalfSize,
C->getSExtValue()))
9075 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9114 switch (OrigSimpleTy) {
9130 unsigned ExtOpcode) {
9153 if (ExtendedTy == LD->getMemoryVT())
9154 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9155 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9156 LD->getMemOperand()->getFlags());
9162 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9163 LD->getMemoryVT(), LD->getAlign(),
9164 LD->getMemOperand()->getFlags());
9177 N->getOperand(0)->getValueType(0),
9183 "Expected extending load");
9189 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9198 SDNode *BVN =
N->getOperand(0).getNode();
9200 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9208 EVT VT =
N->getValueType(0);
9214 for (
unsigned i = 0; i != NumElts; ++i) {
9215 const APInt &CInt =
N->getConstantOperandAPInt(i);
9224 unsigned Opcode =
N->getOpcode();
9226 SDNode *N0 =
N->getOperand(0).getNode();
9227 SDNode *N1 =
N->getOperand(1).getNode();
9235 unsigned Opcode =
N->getOpcode();
9237 SDNode *N0 =
N->getOperand(0).getNode();
9238 SDNode *N1 =
N->getOperand(1).getNode();
9248 EVT VT =
Op.getValueType();
9250 "unexpected type for custom-lowering ISD::MUL");
9251 SDNode *N0 =
Op.getOperand(0).getNode();
9252 SDNode *N1 =
Op.getOperand(1).getNode();
9253 unsigned NewOpc = 0;
9257 if (isN0SExt && isN1SExt)
9258 NewOpc = ARMISD::VMULLs;
9262 if (isN0ZExt && isN1ZExt)
9263 NewOpc = ARMISD::VMULLu;
9264 else if (isN1SExt || isN1ZExt) {
9268 NewOpc = ARMISD::VMULLs;
9271 NewOpc = ARMISD::VMULLu;
9275 NewOpc = ARMISD::VMULLu;
9281 if (VT == MVT::v2i64)
9298 "unexpected types for extended operands to VMULL");
9299 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9334 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9368 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9371 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9392 EVT VT =
Op.getValueType();
9393 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9394 "unexpected type for custom-lowering ISD::SDIV");
9401 if (VT == MVT::v8i8) {
9429 EVT VT =
Op.getValueType();
9430 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9431 "unexpected type for custom-lowering ISD::UDIV");
9438 if (VT == MVT::v8i8) {
9477 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9480 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9484 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9504 unsigned Opcode,
bool IsSigned) {
9505 EVT VT0 =
Op.getValue(0).getValueType();
9506 EVT VT1 =
Op.getValue(1).getValueType();
9508 bool InvertCarry = Opcode == ARMISD::SUBE;
9528 EVT VT =
Op.getValueType();
9529 assert((VT == MVT::i32 || VT == MVT::i64) &&
9530 "unexpected type for custom lowering DIV");
9536 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9538 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9545 for (
auto AI : {1, 0}) {
9546 SDValue Operand =
Op.getOperand(AI);
9547 Args.emplace_back(Operand,
9564ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9572 const bool MinSize =
ST.hasMinSize();
9573 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9574 :
ST.hasDivideInARMMode();
9578 if (
N->getOperand(0).getValueType().isVector())
9583 if (!(MinSize && HasDivide))
9590 return SDValue(
N, 0);
9596 if (Divisor.
sgt(128))
9599 return SDValue(
N, 0);
9604 assert(
Op.getValueType() == MVT::i32 &&
9605 "unexpected type for custom lowering DIV");
9608 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9611 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9617 if (
N->getValueType(0) == MVT::i32)
9618 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9621 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9625void ARMTargetLowering::ExpandDIV_Windows(
9630 assert(
Op.getValueType() == MVT::i64 &&
9631 "unexpected type for custom lowering DIV");
9636 SDValue
Result = LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9646std::pair<SDValue, SDValue>
9647ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9653 EVT MemVT =
LD->getMemoryVT();
9654 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9655 return std::make_pair(SDValue(), SDValue());
9658 unsigned AS =
LD->getAddressSpace();
9661 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9663 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9671 Opts, dl,
LD->getChain());
9678 SDValue EN = DAG.
getNode(ExtType, dl,
LD->getValueType(0), Pair.first);
9687 return std::make_pair(SDValue(), SDValue());
9696 EVT MemVT =
ST->getMemoryVT();
9697 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9701 unsigned AS =
ST->getAddressSpace();
9704 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9706 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9714 SDValue StoreVal =
ST->getOperand(1);
9715 if (
ST->isTruncatingStore())
9720 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9721 dl,
ST->getChain());
9723 return CallResult.second;
9734 EVT MemVT = LD->getMemoryVT();
9735 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9736 MemVT == MVT::v16i1) &&
9737 "Expected a predicate type!");
9738 assert(MemVT ==
Op.getValueType());
9740 "Expected a non-extending load");
9741 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9755 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9757 LD->getMemOperand());
9763 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9764 if (MemVT != MVT::v16i1)
9773 EVT MemVT =
LD->getMemoryVT();
9775 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9776 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9777 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9778 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9781 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9782 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9787 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9788 auto Pair = LowerAEABIUnalignedLoad(SDValue(
N, 0), DAG);
9790 Results.push_back(Pair.first);
9791 Results.push_back(Pair.second);
9798 EVT MemVT = ST->getMemoryVT();
9799 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9800 MemVT == MVT::v16i1) &&
9801 "Expected a predicate type!");
9802 assert(MemVT == ST->getValue().getValueType());
9803 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9804 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9809 SDValue Build = ST->getValue();
9810 if (MemVT != MVT::v16i1) {
9823 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9829 ST->getChain(), dl, GRP, ST->getBasePtr(),
9831 ST->getMemOperand());
9837 EVT MemVT =
ST->getMemoryVT();
9839 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9840 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
9841 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9842 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
9843 SDNode *
N =
Op.getNode();
9856 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
9857 MemVT,
ST->getMemOperand());
9858 }
else if (Subtarget->hasMVEIntegerOps() &&
9859 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9860 MemVT == MVT::v16i1))) {
9862 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9863 return LowerAEABIUnalignedStore(
Op, DAG);
9870 (
N->getOpcode() == ARMISD::VMOVIMM &&
9876 MVT VT =
Op.getSimpleValueType();
9878 SDValue PassThru =
N->getPassThru();
9889 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
9890 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
9891 N->getExtensionType(),
N->isExpandingLoad());
9894 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
9896 if (!PassThru.
isUndef() && !PassThruIsCastZero)
9903 if (!ST->hasMVEIntegerOps())
9907 unsigned BaseOpcode = 0;
9908 switch (
Op->getOpcode()) {
9924 unsigned NumActiveLanes = NumElts;
9926 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
9927 NumActiveLanes == 2) &&
9928 "Only expected a power 2 vector size");
9932 while (NumActiveLanes > 4) {
9933 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
9935 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
9936 NumActiveLanes /= 2;
9940 if (NumActiveLanes == 4) {
9950 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
9951 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
9952 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
9958 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
9962 if (EltVT !=
Op->getValueType(0))
9969 if (!ST->hasMVEFloatOps())
9984 unsigned PairwiseIntrinsic = 0;
9985 switch (
Op->getOpcode()) {
9989 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
9992 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
9995 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
9998 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10004 unsigned NumActiveLanes = NumElts;
10006 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10007 NumActiveLanes == 2) &&
10008 "Only expected a power 2 vector size");
10014 VT =
Lo.getValueType();
10016 NumActiveLanes /= 2;
10020 while (NumActiveLanes > 1) {
10022 NumActiveLanes /= 2;
10029 if (EltVT !=
Op.getValueType()) {
10030 unsigned Extend = 0;
10031 switch (
Op->getOpcode()) {
10043 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10083 SDLoc dl(V0.getNode());
10088 const SDValue Ops[] = {RegClass, V0, SubReg0,
V1, SubReg1};
10094 SDLoc dl(V.getNode());
10095 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10105 assert(
N->getValueType(0) == MVT::i64 &&
10106 "AtomicCmpSwap on types less than 64 should be legal");
10115 ARM::CMP_SWAP_64,
SDLoc(
N),
10116 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10135 EVT VT =
Op.getValueType();
10136 SDValue Chain =
Op.getOperand(0);
10137 SDValue
LHS =
Op.getOperand(1);
10138 SDValue
RHS =
Op.getOperand(2);
10144 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10146 Chain, IsSignaling);
10147 if (!
RHS.getNode()) {
10161 SDValue ARMcc = DAG.
getConstant(CondCode, dl, MVT::i32);
10162 SDValue
Cmp = getVFPCmp(
LHS,
RHS, DAG, dl, IsSignaling);
10165 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10166 Result = getCMOV(dl, VT, Result,
True, ARMcc, Cmp, DAG);
10183 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10186 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10192 SDValue
LHS =
Op.getOperand(0);
10193 SDValue
RHS =
Op.getOperand(1);
10199 if (!IsSigned && Subtarget->isThumb1Only()) {
10208 SDValue Sub1WithFlags = DAG.
getNode(
10210 SDValue Sub1Result = Sub1WithFlags.
getValue(0);
10211 SDValue Flags1 = Sub1WithFlags.
getValue(1);
10217 Sub1Result, Sub1Result, Flags1);
10218 SDValue Sbc1Result = Sbc1.
getValue(0);
10227 SDValue Sbc2Result = Sbc2.
getValue(0);
10232 if (
Op.getValueType() != MVT::i32)
10246 unsigned Opcode = ARMISD::SUBC;
10250 SDValue SubLHS =
RHS.getOperand(0);
10251 SDValue SubRHS =
RHS.getOperand(1);
10255 bool CanUseAdd =
false;
10271 Opcode = ARMISD::ADDC;
10279 SDValue OpWithFlags =
10282 SDValue OpResult = OpWithFlags.
getValue(0);
10294 SDValue GTCondValue = DAG.
getConstant(GTCond, dl, MVT::i32);
10295 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10296 GTCondValue, Flags);
10299 SDValue LTCondValue = DAG.
getConstant(LTCond, dl, MVT::i32);
10300 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10301 LTCondValue, Flags);
10303 if (
Op.getValueType() != MVT::i32)
10311 switch (
Op.getOpcode()) {
10345 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10349 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10350 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10372 return LowerSET_FPMODE(
Op, DAG);
10374 return LowerRESET_FPMODE(
Op, DAG);
10378 !
Op.getValueType().isVector())
10379 return LowerDIV_Windows(
Op, DAG,
true);
10383 !
Op.getValueType().isVector())
10384 return LowerDIV_Windows(
Op, DAG,
false);
10400 return LowerALUO(
Op, DAG);
10408 EVT MemVT = LD->getMemoryVT();
10409 if (Subtarget->hasMVEIntegerOps() &&
10410 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10411 MemVT == MVT::v16i1))
10414 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10420 return LowerSTORE(
Op, DAG, Subtarget);
10445 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10454 return LowerSPONENTRY(
Op, DAG);
10456 return LowerFP_TO_BF16(
Op, DAG);
10457 case ARMISD::WIN__DBZCHK:
return SDValue();
10460 return LowerCMP(
Op, DAG);
10462 return LowerABS(
Op, DAG);
10467 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10468 Op.getOperand(1).getValueType() == MVT::bf16) &&
10469 "Expected custom lowering of rounding operations only for f16");
10472 {
Op.getOperand(0),
Op.getOperand(1)});
10473 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10474 {Ext.getValue(1), Ext.getValue(0)});
10481 unsigned IntNo =
N->getConstantOperandVal(0);
10483 if (IntNo == Intrinsic::arm_smlald)
10484 Opc = ARMISD::SMLALD;
10485 else if (IntNo == Intrinsic::arm_smlaldx)
10486 Opc = ARMISD::SMLALDX;
10487 else if (IntNo == Intrinsic::arm_smlsld)
10488 Opc = ARMISD::SMLSLD;
10489 else if (IntNo == Intrinsic::arm_smlsldx)
10490 Opc = ARMISD::SMLSLDX;
10496 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10500 N->getOperand(1),
N->getOperand(2),
10512 switch (
N->getOpcode()) {
10519 Res = ExpandBITCAST(
N, DAG, Subtarget);
10528 Res = LowerREM(
N, DAG);
10532 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10549 "can only expand DIV on Windows");
10561 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10590 "ROPI/RWPI not currently supported with SjLj");
10599 bool isThumb = Subtarget->isThumb();
10600 bool isThumb2 = Subtarget->
isThumb2();
10603 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10609 : &ARM::GPRRegClass;
10715 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10718 MachineRegisterInfo *MRI = &MF->
getRegInfo();
10723 : &ARM::GPRnopcRegClass;
10727 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10728 unsigned MaxCSNum = 0;
10729 for (MachineBasicBlock &BB : *MF) {
10735 for (MachineInstr &
II : BB) {
10736 if (!
II.isEHLabel())
10739 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10740 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10742 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10743 for (
unsigned Idx : CallSiteIdxs) {
10744 CallSiteNumToLPad[
Idx].push_back(&BB);
10745 MaxCSNum = std::max(MaxCSNum, Idx);
10752 std::vector<MachineBasicBlock*> LPadList;
10753 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10754 LPadList.reserve(CallSiteNumToLPad.
size());
10755 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10756 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10757 for (MachineBasicBlock *
MBB : MBBList) {
10758 LPadList.push_back(
MBB);
10763 assert(!LPadList.empty() &&
10764 "No landing pad destinations for the dispatch jump table!");
10767 MachineJumpTableInfo *JTI =
10774 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10777 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10779 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10782 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10786 MF->insert(MF->end(), DispatchBB);
10787 MF->insert(MF->end(), DispContBB);
10788 MF->insert(MF->end(), TrapBB);
10792 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10794 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10798 MachineInstrBuilder MIB;
10799 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10801 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10811 unsigned NumLPads = LPadList.size();
10812 if (Subtarget->isThumb2()) {
10814 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10820 if (NumLPads < 256) {
10821 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10823 .
addImm(LPadList.size())
10827 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10828 .
addImm(NumLPads & 0xFFFF)
10831 unsigned VReg2 = VReg1;
10832 if ((NumLPads & 0xFFFF0000) != 0) {
10834 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10840 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
10846 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
10852 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
10857 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
10864 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
10868 }
else if (Subtarget->isThumb()) {
10870 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
10876 if (NumLPads < 256) {
10877 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
10882 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10884 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
10887 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
10891 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
10895 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
10901 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
10907 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
10914 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
10919 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
10925 MachineMemOperand *JTMMOLd =
10930 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
10936 unsigned NewVReg6 = NewVReg5;
10937 if (IsPositionIndependent) {
10939 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
10946 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
10951 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
10957 if (NumLPads < 256) {
10958 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
10962 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
10964 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
10965 .
addImm(NumLPads & 0xFFFF)
10968 unsigned VReg2 = VReg1;
10969 if ((NumLPads & 0xFFFF0000) != 0) {
10971 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
10977 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
10982 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10984 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
10987 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
10991 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
10996 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11008 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11014 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11018 MachineMemOperand *JTMMOLd =
11022 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11029 if (IsPositionIndependent) {
11030 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11035 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11042 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11043 for (MachineBasicBlock *CurMBB : LPadList) {
11044 if (SeenMBBs.
insert(CurMBB).second)
11051 for (MachineBasicBlock *BB : InvokeBBs) {
11055 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11056 while (!Successors.empty()) {
11057 MachineBasicBlock *SMBB = Successors.pop_back_val();
11059 BB->removeSuccessor(SMBB);
11065 BB->normalizeSuccProbs();
11072 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11073 if (!
II->isCall())
continue;
11075 DenseSet<unsigned> DefRegs;
11077 OI =
II->operands_begin(), OE =
II->operands_end();
11079 if (!OI->isReg())
continue;
11080 DefRegs.
insert(OI->getReg());
11083 MachineInstrBuilder MIB(*MF, &*
II);
11085 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11086 unsigned Reg = SavedRegs[i];
11087 if (Subtarget->isThumb2() &&
11088 !ARM::tGPRRegClass.contains(
Reg) &&
11089 !ARM::hGPRRegClass.contains(
Reg))
11091 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11093 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11105 for (MachineBasicBlock *MBBLPad : MBBLPads)
11106 MBBLPad->setIsEHPad(
false);
11109 MI.eraseFromParent();
11122static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11124 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11125 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11127 return LdSize == 4 ? ARM::tLDRi
11128 : LdSize == 2 ? ARM::tLDRHi
11129 : LdSize == 1 ? ARM::tLDRBi : 0;
11131 return LdSize == 4 ? ARM::t2LDR_POST
11132 : LdSize == 2 ? ARM::t2LDRH_POST
11133 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11134 return LdSize == 4 ? ARM::LDR_POST_IMM
11135 : LdSize == 2 ? ARM::LDRH_POST
11136 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11141static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11143 return StSize == 16 ? ARM::VST1q32wb_fixed
11144 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11146 return StSize == 4 ? ARM::tSTRi
11147 : StSize == 2 ? ARM::tSTRHi
11148 : StSize == 1 ? ARM::tSTRBi : 0;
11150 return StSize == 4 ? ARM::t2STR_POST
11151 : StSize == 2 ? ARM::t2STRH_POST
11152 : StSize == 1 ? ARM::t2STRB_POST : 0;
11153 return StSize == 4 ? ARM::STR_POST_IMM
11154 : StSize == 2 ? ARM::STRH_POST
11155 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11162 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11163 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11164 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11165 assert(LdOpc != 0 &&
"Should have a load opcode");
11172 }
else if (IsThumb1) {
11178 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11183 }
else if (IsThumb2) {
11203 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11204 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11205 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11206 assert(StOpc != 0 &&
"Should have a store opcode");
11208 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11213 }
else if (IsThumb1) {
11220 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11225 }
else if (IsThumb2) {
11226 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11232 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11247 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11253 unsigned SizeVal =
MI.getOperand(2).getImm();
11258 MachineRegisterInfo &MRI = MF->
getRegInfo();
11259 unsigned UnitSize = 0;
11263 bool IsThumb1 = Subtarget->isThumb1Only();
11264 bool IsThumb2 = Subtarget->isThumb2();
11265 bool IsThumb = Subtarget->isThumb();
11267 if (Alignment & 1) {
11269 }
else if (Alignment & 2) {
11274 Subtarget->hasNEON()) {
11275 if ((Alignment % 16 == 0) && SizeVal >= 16)
11277 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11286 bool IsNeon = UnitSize >= 8;
11287 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11289 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11290 : UnitSize == 8 ? &ARM::DPRRegClass
11293 unsigned BytesLeft = SizeVal % UnitSize;
11294 unsigned LoopSize = SizeVal - BytesLeft;
11296 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11300 unsigned srcIn = src;
11301 unsigned destIn = dest;
11302 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11307 IsThumb1, IsThumb2);
11309 IsThumb1, IsThumb2);
11317 for (
unsigned i = 0; i < BytesLeft; i++) {
11322 IsThumb1, IsThumb2);
11324 IsThumb1, IsThumb2);
11328 MI.eraseFromParent();
11354 MF->
insert(It, loopMBB);
11355 MF->
insert(It, exitMBB);
11358 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11369 if (Subtarget->useMovt()) {
11370 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11373 }
else if (Subtarget->genExecuteOnly()) {
11374 assert(IsThumb &&
"Non-thumb expected to have used movt");
11379 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11384 MachineMemOperand *CPMMO =
11408 MachineBasicBlock *entryBB = BB;
11423 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11431 IsThumb1, IsThumb2);
11433 IsThumb1, IsThumb2);
11437 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11443 MachineInstrBuilder MIB =
11445 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11454 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11463 auto StartOfExit = exitMBB->
begin();
11467 unsigned srcIn = srcLoop;
11468 unsigned destIn = destLoop;
11469 for (
unsigned i = 0; i < BytesLeft; i++) {
11473 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11474 IsThumb1, IsThumb2);
11475 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11476 IsThumb1, IsThumb2);
11481 MI.eraseFromParent();
11489 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11492 assert(TM.getTargetTriple().isOSWindows() &&
11493 "__chkstk is only supported on Windows");
11494 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11514 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11515 if (ChkStkLibcall == RTLIB::Unsupported)
11519 switch (TM.getCodeModel()) {
11563 MI.eraseFromParent();
11572 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11587 .
addReg(
MI.getOperand(0).getReg())
11595 MI.eraseFromParent();
11619 if (miI == BB->
end()) {
11621 if (Succ->isLiveIn(ARM::CPSR))
11627 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11640 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11647 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11654 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11657 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11658 .
addUse(TotalIterationsReg)
11665 return TotalIterationsReg;
11676 Register TotalIterationsReg,
bool IsMemcpy) {
11685 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11695 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11703 Register RemainingLoopIterationsReg =
11705 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11706 .
addUse(TotalIterationsReg)
11708 .
addUse(RemainingLoopIterationsReg)
11714 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11715 .
addUse(ElementCountReg)
11717 .
addUse(RemainingElementsReg)
11722 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11723 .
addUse(PredCounterPhiReg)
11728 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11729 .
addUse(PredCounterPhiReg)
11738 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11747 SrcValueReg = OpSrcReg;
11749 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11760 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11761 .
addUse(LoopCounterPhiReg)
11764 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11765 .
addUse(RemainingLoopIterationsReg)
11783 "Invalid call instruction for a KCFI check");
11786 switch (
MBBI->getOpcode()) {
11789 case ARM::BLX_pred:
11790 case ARM::BLX_noip:
11791 case ARM::BLX_pred_noip:
11793 TargetOp = &
MBBI->getOperand(0);
11795 case ARM::TCRETURNri:
11796 case ARM::TCRETURNrinotr12:
11797 case ARM::TAILJMPr:
11798 case ARM::TAILJMPr4:
11799 TargetOp = &
MBBI->getOperand(0);
11805 case ARM::tBLXr_noip:
11806 case ARM::tBX_CALL:
11807 TargetOp = &
MBBI->getOperand(2);
11810 case ARM::tTAILJMPr:
11811 TargetOp = &
MBBI->getOperand(0);
11817 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11821 unsigned KCFICheckOpcode;
11822 if (Subtarget->isThumb()) {
11823 if (Subtarget->isThumb2()) {
11824 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11826 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11829 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11843 bool isThumb2 = Subtarget->isThumb2();
11844 switch (
MI.getOpcode()) {
11851 case ARM::tLDR_postidx: {
11855 .
add(
MI.getOperand(2))
11856 .
add(
MI.getOperand(3))
11857 .
add(
MI.getOperand(4))
11858 .
add(
MI.getOperand(0))
11860 MI.eraseFromParent();
11864 case ARM::MVE_MEMCPYLOOPINST:
11865 case ARM::MVE_MEMSETLOOPINST: {
11895 Register OpDestReg =
MI.getOperand(0).getReg();
11896 Register OpSrcReg =
MI.getOperand(1).getReg();
11897 Register OpSizeReg =
MI.getOperand(2).getReg();
11917 if (TpExit == BB) {
11919 "block containing memcpy/memset Pseudo");
11929 genTPEntry(TpEntry, TpLoopBody, TpExit, OpSizeReg,
TII, dl, MRI);
11932 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
11934 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
11937 Properties.resetNoPHIs();
11949 MI.eraseFromParent();
11959 case ARM::t2STR_preidx:
11960 MI.setDesc(
TII->get(ARM::t2STR_PRE));
11962 case ARM::t2STRB_preidx:
11963 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
11965 case ARM::t2STRH_preidx:
11966 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
11969 case ARM::STRi_preidx:
11970 case ARM::STRBi_preidx: {
11971 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
11972 : ARM::STRB_PRE_IMM;
11974 unsigned Offset =
MI.getOperand(4).getImm();
11982 .
add(
MI.getOperand(0))
11983 .
add(
MI.getOperand(1))
11984 .
add(
MI.getOperand(2))
11986 .
add(
MI.getOperand(5))
11987 .
add(
MI.getOperand(6))
11989 MI.eraseFromParent();
11992 case ARM::STRr_preidx:
11993 case ARM::STRBr_preidx:
11994 case ARM::STRH_preidx: {
11996 switch (
MI.getOpcode()) {
11998 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
11999 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12000 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12005 MI.eraseFromParent();
12009 case ARM::tMOVCCr_pseudo: {
12027 F->insert(It, copy0MBB);
12028 F->insert(It, sinkMBB);
12031 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12037 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12053 .
addImm(
MI.getOperand(3).getImm())
12054 .
addReg(
MI.getOperand(4).getReg());
12069 .
addReg(
MI.getOperand(1).getReg())
12071 .
addReg(
MI.getOperand(2).getReg())
12074 MI.eraseFromParent();
12079 case ARM::BCCZi64: {
12085 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12090 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12094 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12100 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12104 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12114 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12123 MI.eraseFromParent();
12127 case ARM::Int_eh_sjlj_setjmp:
12128 case ARM::Int_eh_sjlj_setjmp_nofp:
12129 case ARM::tInt_eh_sjlj_setjmp:
12130 case ARM::t2Int_eh_sjlj_setjmp:
12131 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12134 case ARM::Int_eh_sjlj_setup_dispatch:
12135 EmitSjLjDispatchBlock(
MI, BB);
12137 case ARM::COPY_STRUCT_BYVAL_I32:
12139 return EmitStructByval(
MI, BB);
12140 case ARM::WIN__CHKSTK:
12141 return EmitLowered__chkstk(
MI, BB);
12142 case ARM::WIN__DBZCHK:
12143 return EmitLowered__dbzchk(
MI, BB);
12159 if (!
Node->hasAnyUseOfValue(0)) {
12160 MI.getOperand(0).setIsDead(
true);
12162 if (!
Node->hasAnyUseOfValue(1)) {
12163 MI.getOperand(1).setIsDead(
true);
12167 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12169 : &ARM::GPRRegClass);
12176 if (
MI.getOpcode() == ARM::MEMCPY) {
12197 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12198 &&
"converted opcode should be the same except for cc_out"
12199 " (and, on Thumb1, pred)");
12207 if (Subtarget->isThumb1Only()) {
12208 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12209 MI.addOperand(
MI.getOperand(1));
12210 MI.removeOperand(1);
12214 for (
unsigned i =
MI.getNumOperands(); i--;) {
12216 if (
op.isReg() &&
op.isUse()) {
12219 MI.tieOperands(DefIdx, i);
12227 ccOutIdx =
MCID->getNumOperands() - 1;
12229 ccOutIdx =
MCID->getNumOperands() - 1;
12233 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12234 assert(!NewOpc &&
"Optional cc_out operand required");
12240 bool deadCPSR =
false;
12241 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12248 MI.removeOperand(i);
12253 assert(!NewOpc &&
"Optional cc_out operand required");
12256 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12258 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12259 "expect uninitialized optional cc_out operand");
12261 if (!Subtarget->isThumb1Only())
12298 switch (
N->getOpcode()) {
12299 default:
return false;
12301 CC =
N->getOperand(0);
12323 EVT VT =
N->getValueType(0);
12324 CC =
N->getOperand(0);
12371 EVT VT =
N->getValueType(0);
12374 bool SwapSelectOps;
12376 NonConstantVal, DAG))
12382 OtherOp, NonConstantVal);
12388 CCOp, TrueVal, FalseVal);
12408 if (
N->getOpcode() == ARMISD::VUZP)
12412 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12427 if (!
N->getValueType(0).is64BitVector())
12435 EVT VT =
N->getValueType(0);
12474 EVT VT =
N->getValueType(0);
12480 Opcode = Intrinsic::arm_neon_vpaddls;
12482 Opcode = Intrinsic::arm_neon_vpaddlu;
12510 EVT VT =
N->getValueType(0);
12525 unsigned nextIndex = 0;
12576 Ops.push_back(Vec);
12593 return DAG.
getNode(ExtOp, dl, VT, tmp);
12624 if (SRA.getOpcode() !=
ISD::SRA) {
12631 if (Const->getZExtValue() != 31)
12636 if (SRA.getOperand(0) !=
Mul)
12640 SDLoc dl(AddcNode);
12641 unsigned Opcode = 0;
12646 Opcode = ARMISD::SMLALBB;
12647 Op0 =
Mul.getOperand(0);
12648 Op1 =
Mul.getOperand(1);
12650 Opcode = ARMISD::SMLALBT;
12651 Op0 =
Mul.getOperand(0);
12652 Op1 =
Mul.getOperand(1).getOperand(0);
12654 Opcode = ARMISD::SMLALTB;
12655 Op0 =
Mul.getOperand(0).getOperand(0);
12656 Op1 =
Mul.getOperand(1);
12658 Opcode = ARMISD::SMLALTT;
12659 Op0 =
Mul->getOperand(0).getOperand(0);
12660 Op1 =
Mul->getOperand(1).getOperand(0);
12676 SDValue resNode(AddcNode, 0);
12704 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12705 "Expect an ADDE or SUBE");
12709 "ADDE node has the wrong inputs");
12713 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12714 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12715 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12716 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12728 "Expect ADDC with two result values. First: i32");
12732 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12748 bool IsLeftOperandMUL =
false;
12753 IsLeftOperandMUL =
true;
12764 SDValue *LowAddSub =
nullptr;
12767 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12770 if (IsLeftOperandMUL)
12771 HiAddSub = &AddeSubeOp1;
12773 HiAddSub = &AddeSubeOp0;
12778 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12779 LoMul = &AddcSubcOp0;
12780 LowAddSub = &AddcSubcOp1;
12782 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12783 LoMul = &AddcSubcOp1;
12784 LowAddSub = &AddcSubcOp0;
12792 if (AddcSubcNode == HiAddSub->getNode() ||
12808 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12813 Ops.push_back(*HiAddSub);
12814 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12815 FinalOpc = ARMISD::SMMLSR;
12817 FinalOpc = ARMISD::SMMLAR;
12822 return SDValue(AddeSubeNode, 0);
12823 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12829 Ops.push_back(*LowAddSub);
12830 Ops.push_back(*HiAddSub);
12843 return SDValue(AddeSubeNode, 0);
12855 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12860 if (AddcNode->
getOpcode() != ARMISD::ADDC)
12864 SDNode *UmlalNode =
nullptr;
12903 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12908 SDNode* AddcNode =
N->getOperand(2).getNode();
12909 SDNode* AddeNode =
N->getOperand(3).getNode();
12910 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
12911 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
12917 {N->getOperand(0), N->getOperand(1),
12918 AddcNode->getOperand(0), AddcNode->getOperand(1)});
12928 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
12932 if (
LHS->getOpcode() == ARMISD::ADDE &&
12942 int32_t imm =
C->getSExtValue();
12943 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
12946 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
12948 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
12963 int64_t imm =
C->getSExtValue();
12972 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
12974 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
12975 N->getOperand(0),
RHS,
N->getOperand(2));
12987 if (!Subtarget->hasMVEIntegerOps())
13000 SetCC =
N->getOperand(0);
13004 TrueVal =
N->getOperand(1);
13005 FalseVal =
N->getOperand(2);
13007 LHS =
N->getOperand(0);
13008 RHS =
N->getOperand(1);
13010 TrueVal =
N->getOperand(2);
13011 FalseVal =
N->getOperand(3);
13016 unsigned int Opcode = 0;
13020 Opcode = ARMISD::VMINVu;
13026 Opcode = ARMISD::VMINVs;
13032 Opcode = ARMISD::VMAXVu;
13038 Opcode = ARMISD::VMAXVs;
13045 switch (TrueVal->getOpcode()) {
13064 if (TrueVal !=
LHS || FalseVal !=
RHS)
13067 EVT LeftType =
LHS->getValueType(0);
13068 EVT RightType =
RHS->getValueType(0);
13071 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13075 if (VectorScalarType != MVT::i32)
13083 if (VectorScalarType != MVT::i32)
13096 EVT VT =
N->getValueType(0);
13104 Shft =
N->getOperand(0);
13111 Cmp.getOperand(0) !=
N->getOperand(1) ||
13112 Cmp.getOperand(1) !=
N->getOperand(2))
13114 Shft =
N->getOperand(1);
13126 ScalarType = MVT::i8;
13129 case (1 << 15) - 1:
13130 ScalarType = MVT::i16;
13133 case (1ULL << 31) - 1:
13134 ScalarType = MVT::i32;
13165 unsigned LegalLanes = 128 / (ShftAmt + 1);
13177 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13178 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13179 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13180 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13189 for (
unsigned I = 0;
I < NumParts; ++
I) {
13196 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13206 if (!Subtarget->hasMVEIntegerOps())
13211 if (
N->getOperand(0).getOpcode() == ARMISD::PREDICATE_CAST &&
13213 unsigned C =
N->getOperand(0).getConstantOperandVal(0);
13215 return N->getOperand(2);
13217 return N->getOperand(1);
13232 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13242 if (!Const || !Const->isOne())
13260 EVT VT =
N->getValueType(0);
13262 if (!Subtarget->hasMVEIntegerOps() ||
13291 Opc = Intrinsic::arm_mve_vctp32;
13294 Opc = Intrinsic::arm_mve_vctp16;
13297 Opc = Intrinsic::arm_mve_vctp8;
13351 EVT VT =
N->getValueType(0);
13357 switch (
Op.getOpcode()) {
13359 case ARMISD::VADDVs:
13360 case ARMISD::VADDVu:
13361 case ARMISD::VMLAVs:
13362 case ARMISD::VMLAVu:
13382 unsigned N0RedOp = 0;
13389 unsigned N1RedOp = 0;
13403 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13405 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13412 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13436 if (!BaseLocDecomp0.getBase() ||
13437 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13438 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13440 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13442 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13452 if (IsBefore < 0) {
13455 }
else if (IsBefore > 0) {
13468 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13478 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13488 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13490 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13497 if (!Subtarget->hasMVEIntegerOps())
13503 EVT VT =
N->getValueType(0);
13508 if (VT != MVT::i64)
13519 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13539 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13548 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13550 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13552 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13554 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13556 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13558 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13560 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13562 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13564 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13566 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13568 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13570 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13572 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13574 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13576 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13578 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13588 "Expected shift op");
13590 SDValue ShiftLHS =
N->getOperand(0);
13604 if (Subtarget->isThumb1Only()) {
13615 if (Const->getAPIntValue().ult(256))
13618 Const->getAPIntValue().sgt(-256))
13634 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13635 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13636 "Expected XOR(SHIFT) pattern");
13641 if (XorC && ShiftC) {
13642 unsigned MaskIdx, MaskLen;
13643 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13644 unsigned ShiftAmt = ShiftC->getZExtValue();
13645 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13646 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13647 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13648 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13658 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13660 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13661 "Expected shift-shift mask");
13663 if (!Subtarget->isThumb1Only())
13666 EVT VT =
N->getValueType(0);
13674 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13676 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13681 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps()) {
13682 if (Subtarget->isThumb1Only())
13696 return Subtarget->hasVFP2Base();
13698 return Subtarget->hasVFP2Base();
13700 return Subtarget->hasFP64();
13703 return Subtarget->hasMVEFloatOps();
13732 if (ST->isThumb1Only())
13736 for (
auto *U :
N->users()) {
13737 switch(U->getOpcode()) {
13755 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13756 U->getOperand(1).getOpcode() ==
ISD::SHL)
13766 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13773 if (!C1ShlC2 || !C2)
13776 APInt C2Int = C2->getAPIntValue();
13777 APInt C1Int = C1ShlC2->getAPIntValue();
13779 if (C2Int.
uge(C2Width))
13785 if ((C1Int & Mask) != C1Int)
13792 auto LargeImm = [](
const APInt &
Imm) {
13793 unsigned Zeros =
Imm.countl_zero() +
Imm.countr_zero();
13794 return Imm.getBitWidth() - Zeros > 8;
13797 if (LargeImm(C1Int) || LargeImm(C2Int))
13809 SHL.dump();
N->dump());
13870 if (
Op.hasOneUse() && ShiftAmt &&
13871 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
13929 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
13950 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
13971 if (!Subtarget->hasVMLxForwarding())
13990 EVT VT =
N->getValueType(0);
14001 EVT VT =
N->getValueType(0);
14002 if (VT != MVT::v2i64)
14013 return Op->getOperand(0);
14027 And =
And->getOperand(0);
14032 Mask = Mask->getOperand(0);
14035 Mask.getValueType() != MVT::v4i32)
14041 return And->getOperand(0);
14046 if (
SDValue Op0 = IsSignExt(N0)) {
14047 if (
SDValue Op1 = IsSignExt(N1)) {
14048 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14049 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14050 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14053 if (
SDValue Op0 = IsZeroExt(N0)) {
14054 if (
SDValue Op1 = IsZeroExt(N1)) {
14055 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14056 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14057 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14069 EVT VT =
N->getValueType(0);
14070 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14081 if (VT != MVT::i32)
14088 int64_t MulAmt =
C->getSExtValue();
14091 ShiftAmt = ShiftAmt & (32 - 1);
14096 MulAmt >>= ShiftAmt;
14157 if (
N->getValueType(0) != MVT::i32)
14166 if (C1 == 255 || C1 == 65535)
14169 SDNode *N0 =
N->getOperand(0).getNode();
14183 if (!C2 || C2 >= 32)
14227 if (Trailing == C2 && C2 + C3 < 32) {
14240 if (Leading == C2 && C2 + C3 < 32) {
14268 EVT VT =
N->getValueType(0);
14272 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14275 APInt SplatBits, SplatUndef;
14276 unsigned SplatBitSize;
14278 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14279 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14280 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14281 SplatBitSize == 64) {
14288 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14290 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14315 if (!Subtarget->hasV6Ops() ||
14316 (Subtarget->isThumb() &&
14317 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14320 SDValue SRL = OR->getOperand(0);
14321 SDValue SHL = OR->getOperand(1);
14324 SRL = OR->getOperand(1);
14325 SHL = OR->getOperand(0);
14332 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14336 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14337 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14338 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14357 unsigned Opcode = 0;
14358 if (
isS16(OpS16, DAG))
14359 Opcode = ARMISD::SMULWB;
14361 Opcode = ARMISD::SMULWT;
14376 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14379 EVT VT =
N->getValueType(0);
14394 if (VT != MVT::i32)
14407 if (Mask == 0xffff)
14414 if ((Val & ~Mask) != Val)
14420 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14439 (Mask == ~Mask2)) {
14442 if (Subtarget->hasDSP() &&
14443 (Mask == 0xffff || Mask == 0xffff0000))
14449 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14456 (~Mask == Mask2)) {
14459 if (Subtarget->hasDSP() &&
14460 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14516 if (
N->getOpcode() == ARMISD::VCMP)
14518 else if (
N->getOpcode() == ARMISD::VCMPZ)
14526 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14533 EVT VT =
N->getValueType(0);
14538 auto IsFreelyInvertable = [&](
SDValue V) {
14539 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14545 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14563 if (AndOp.getOpcode() !=
ISD::AND)
14567 SDValue Mask = AndOp.getOperand(1);
14577 bool IsShiftRight =
false;
14580 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14581 IsShiftRight =
true;
14584 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14592 APInt RequiredMask = IsShiftRight
14595 if (MaskBits != RequiredMask)
14598 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14608 EVT VT =
N->getValueType(0);
14614 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14615 VT == MVT::v8i1 || VT == MVT::v16i1))
14618 APInt SplatBits, SplatUndef;
14619 unsigned SplatBitSize;
14621 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14622 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14623 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14624 SplatBitSize == 64) {
14631 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14633 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14653 (Subtarget->hasMVEIntegerOps() &&
14654 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14657 return ShiftInsert;
14661 return ShiftInsert;
14675 unsigned SplatBitSize;
14678 APInt SplatBits0, SplatBits1;
14682 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14683 HasAnyUndefs) && !HasAnyUndefs) {
14684 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14685 HasAnyUndefs) && !HasAnyUndefs) {
14690 SplatBits0 == ~SplatBits1) {
14701 DAG.
getNode(ARMISD::VBSP, dl, CanonicalVT, Mask,
LHS,
RHS);
14702 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14722 if (CSINC.
getOpcode() != ARMISD::CSINC)
14724 if (CSINC.
getOpcode() == ARMISD::CSINC &&
14737 EVT VT =
N->getValueType(0);
14752 if (Subtarget->hasMVEIntegerOps()) {
14780 assert(
N->getOpcode() == ARMISD::BFI);
14783 ToMask =
~N->getConstantOperandAPInt(2);
14803 unsigned LastActiveBitInA =
A.countr_zero();
14804 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14805 return LastActiveBitInA - 1 == FirstActiveBitInB;
14810 APInt ToMask, FromMask;
14815 if (V.getOpcode() != ARMISD::BFI)
14818 APInt NewToMask, NewFromMask;
14820 if (NewFrom != From)
14824 if ((NewToMask & ToMask).getBoolValue())
14849 unsigned InvMask =
N->getConstantOperandVal(2);
14853 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14854 "undefined behavior");
14855 unsigned Mask = (1u << Width) - 1;
14857 if ((Mask & (~Mask2)) == 0)
14859 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14866 APInt ToMask1, FromMask1;
14869 APInt ToMask2, FromMask2;
14875 APInt NewFromMask = FromMask1 | FromMask2;
14876 APInt NewToMask = ToMask1 | ToMask2;
14878 EVT VT =
N->getValueType(0);
14881 if (NewFromMask[0] == 0)
14884 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
14892 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
14893 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14894 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14896 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14900 EVT VT =
N->getValueType(0);
14903 N->getOperand(1),
N->getOperand(2));
14915 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
14917 SDValue CSInc = Cmp->getOperand(0);
14927 if (CSInc.
getOpcode() == ARMISD::CSINC &&
14967 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
14968 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
14971 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
14973 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
14986 SDValue InDouble =
N->getOperand(0);
14987 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15001 SDValue BasePtr = LD->getBasePtr();
15003 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15004 LD->getAlign(), LD->getMemOperand()->getFlags());
15010 LD->getPointerInfo().getWithOffset(4),
15012 LD->getMemOperand()->getFlags());
15031 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15045 if (!Subtarget->
isLittle() && BVSwap)
15063 if (!Subtarget->
isLittle() && BVSwap)
15082 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15095 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15108 if (Copy.getValueType() == MVT::f32 &&
15110 bool HasGlue = Copy->getNumOperands() == 3;
15111 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15112 HasGlue ? Copy->getOperand(2) :
SDValue()};
15113 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15132 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15133 LN0->getMemoryVT() == MVT::i16) {
15136 LN0->getBasePtr(), LN0->getMemOperand());
15154 EVT VT =
N->getValueType(0);
15188 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15189 for (
unsigned i = 0; i < NumElts; ++i) {
15190 SDNode *Elt =
N->getOperand(i).getNode();
15207 if (
N->getNumOperands() == 2)
15213 EVT VT =
N->getValueType(0);
15219 for (
unsigned i = 0; i < NumElts; ++i) {
15245 EVT VT =
N->getValueType(0);
15253 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15258 Use->getValueType(0).isFloatingPoint())
15266 unsigned NumOfBitCastedElts = 0;
15268 unsigned NumOfRelevantElts = NumElts;
15269 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15274 ++NumOfBitCastedElts;
15278 --NumOfRelevantElts;
15282 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15300 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15305 V->getOperand(0).getValueType() == MVT::i32)
15307 V = V.getOperand(0);
15324 EVT VT =
N->getValueType(0);
15329 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15331 if (
Op->getOperand(0).getValueType() == VT)
15332 return Op->getOperand(0);
15333 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15340 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15347 if (
Op.getValueType() == MVT::i32) {
15358 EVT VT =
N->getValueType(0);
15363 if (ST->isLittle())
15367 if (
Op.getValueType() == VT)
15374 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15376 if (
Op->getOperand(0).getValueType() == VT)
15377 return Op->getOperand(0);
15378 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15386 if (!Subtarget->hasMVEIntegerOps())
15389 EVT VT =
N->getValueType(0);
15397 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15403 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15407 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15420 EVT VT =
N->getValueType(0);
15421 SDNode *Elt =
N->getOperand(1).getNode();
15436 Vec, V,
N->getOperand(2));
15446 EVT VT =
N->getValueType(0);
15474 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15475 isa<ConstantSDNode>(V->getOperand(1)) &&
15476 V->getConstantOperandVal(1) == Lane + 1 &&
15477 V->getOperand(0).getResNo() == ResNo;
15479 if (OtherIt == Op0->
users().
end())
15484 SDValue OtherExt(*OtherIt, 0);
15496 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15499 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15509 EVT VT =
N->getValueType(0);
15513 if (Op0->
getOpcode() == ARMISD::VDUP) {
15515 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15516 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15517 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15518 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15519 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15522 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15523 X =
X->getOperand(0);
15524 if (
X.getValueType() == VT)
15532 return Op0.
getOperand(
N->getConstantOperandVal(1));
15542 unsigned Offset =
N->getConstantOperandVal(1);
15544 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15554 unsigned Idx =
N->getConstantOperandVal(1);
15569 unsigned Lane =
N->getConstantOperandVal(1);
15597 EVT VT =
N->getValueType(0);
15600 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15602 Op.getOperand(0).getValueType().getScalarType())
15603 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15612 SDValue SubVec =
N->getOperand(1);
15613 uint64_t IdxVal =
N->getConstantOperandVal(2);
15624 if (IdxVal == 0 && Vec.
isUndef())
15630 (IdxVal != 0 && IdxVal != NumSubElts))
15661 ARMISD::VMOVN,
DL, VT,
15667 ARMISD::VMOVN,
DL, VT,
15703 EVT VT =
N->getValueType(0);
15714 unsigned HalfElts = NumElts/2;
15716 for (
unsigned n = 0; n < NumElts; ++n) {
15719 if (MaskElt < (
int)HalfElts)
15721 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15722 NewElt = HalfElts + MaskElt - NumElts;
15765 bool SimpleConstIncOnly,
15773 bool isLoadOp =
true;
15774 bool isLaneOp =
false;
15777 bool hasAlignment =
true;
15778 unsigned NewOpc = 0;
15779 unsigned NumVecs = 0;
15780 if (
Target.isIntrinsic) {
15781 unsigned IntNo =
N->getConstantOperandVal(1);
15785 case Intrinsic::arm_neon_vld1:
15789 case Intrinsic::arm_neon_vld2:
15793 case Intrinsic::arm_neon_vld3:
15797 case Intrinsic::arm_neon_vld4:
15801 case Intrinsic::arm_neon_vld1x2:
15804 hasAlignment =
false;
15806 case Intrinsic::arm_neon_vld1x3:
15809 hasAlignment =
false;
15811 case Intrinsic::arm_neon_vld1x4:
15814 hasAlignment =
false;
15816 case Intrinsic::arm_neon_vld2dup:
15820 case Intrinsic::arm_neon_vld3dup:
15824 case Intrinsic::arm_neon_vld4dup:
15828 case Intrinsic::arm_neon_vld2lane:
15833 case Intrinsic::arm_neon_vld3lane:
15838 case Intrinsic::arm_neon_vld4lane:
15843 case Intrinsic::arm_neon_vst1:
15848 case Intrinsic::arm_neon_vst2:
15849 NewOpc = ARMISD::VST2_UPD;
15853 case Intrinsic::arm_neon_vst3:
15858 case Intrinsic::arm_neon_vst4:
15859 NewOpc = ARMISD::VST4_UPD;
15863 case Intrinsic::arm_neon_vst2lane:
15869 case Intrinsic::arm_neon_vst3lane:
15875 case Intrinsic::arm_neon_vst4lane:
15881 case Intrinsic::arm_neon_vst1x2:
15885 hasAlignment =
false;
15887 case Intrinsic::arm_neon_vst1x3:
15891 hasAlignment =
false;
15893 case Intrinsic::arm_neon_vst1x4:
15897 hasAlignment =
false;
15902 switch (
N->getOpcode()) {
15938 VecTy =
N->getValueType(0);
15939 }
else if (
Target.isIntrinsic) {
15940 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
15943 "Node has to be a load, a store, or an intrinsic!");
15944 VecTy =
N->getOperand(1).getValueType();
15952 if (isLaneOp || isVLDDUPOp)
15955 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
15961 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
15970 EVT AlignedVecTy = VecTy;
15990 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
15991 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16002 Alignment =
Align(1);
16008 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16010 for (n = 0; n < NumResultVecs; ++n)
16011 Tys[n] = AlignedVecTy;
16012 Tys[n++] = MVT::i32;
16013 Tys[n] = MVT::Other;
16018 Ops.push_back(
N->getOperand(0));
16019 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16024 Ops.push_back(StN->getValue());
16028 unsigned LastOperand =
16029 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16030 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16031 Ops.push_back(
N->getOperand(i));
16035 Ops.push_back(DAG.
getConstant(Alignment.value(), dl, MVT::i32));
16039 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16050 for (
unsigned i = 0; i < NumResultVecs; ++i)
16055 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16056 SDValue &LdVal = NewResults[0];
16092 switch (
N->getOpcode()) {
16096 *Ptr =
N->getOperand(0);
16097 *CInc =
N->getOperand(1);
16104 *Ptr =
N->getOperand(1);
16105 *CInc =
N->getOperand(2);
16132 SDValue Addr =
N->getOperand(AddrOpIdx);
16143 unsigned ConstInc =
16148 if (BaseUpdates.
size() >= MaxBaseUpdates)
16169 unsigned UserOffset =
16172 if (!UserOffset || UserOffset <=
Offset)
16175 unsigned NewConstInc = UserOffset -
Offset;
16178 if (BaseUpdates.
size() >= MaxBaseUpdates)
16186 unsigned NumValidUpd = BaseUpdates.
size();
16187 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16198 return LHS.ConstInc <
RHS.ConstInc;
16227 unsigned IntNo =
N->getConstantOperandVal(1);
16228 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16230 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16253 bool isLoadOp =
true;
16254 unsigned NewOpc = 0;
16255 unsigned NumVecs = 0;
16259 case Intrinsic::arm_mve_vld2q:
16263 case Intrinsic::arm_mve_vld4q:
16267 case Intrinsic::arm_mve_vst2q:
16268 NewOpc = ARMISD::VST2_UPD;
16272 case Intrinsic::arm_mve_vst4q:
16273 NewOpc = ARMISD::VST4_UPD;
16282 VecTy =
N->getValueType(0);
16284 VecTy =
N->getOperand(3).getValueType();
16298 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16300 for (n = 0; n < NumResultVecs; ++n)
16302 Tys[n++] = MVT::i32;
16303 Tys[n] = MVT::Other;
16308 Ops.push_back(
N->getOperand(0));
16309 Ops.push_back(
N->getOperand(2));
16310 Ops.push_back(Inc);
16312 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16313 Ops.push_back(
N->getOperand(i));
16320 for (
unsigned i = 0; i < NumResultVecs; ++i)
16339 EVT VT =
N->getValueType(0);
16345 SDNode *VLD =
N->getOperand(0).getNode();
16348 unsigned NumVecs = 0;
16349 unsigned NewOpc = 0;
16351 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16354 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16357 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16369 if (
Use.getResNo() == NumVecs)
16372 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16373 VLDLaneNo !=
User->getConstantOperandVal(1))
16380 for (n = 0; n < NumVecs; ++n)
16382 Tys[n] = MVT::Other;
16392 unsigned ResNo =
Use.getResNo();
16394 if (ResNo == NumVecs)
16401 std::vector<SDValue> VLDDupResults;
16402 for (
unsigned n = 0; n < NumVecs; ++n)
16416 EVT VT =
N->getValueType(0);
16419 if (Subtarget->hasMVEIntegerOps()) {
16423 ExtractVT = MVT::i32;
16425 N->getOperand(0),
N->getOperand(1));
16437 Op =
Op.getOperand(0);
16438 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16442 unsigned EltSize =
Op.getScalarValueSizeInBits();
16444 unsigned Imm =
Op.getConstantOperandVal(0);
16460 if (Subtarget->hasMVEIntegerOps()) {
16463 if (
Op.getValueType() == MVT::f32)
16464 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16466 else if (
Op.getValueType() == MVT::f16)
16467 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16468 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16471 if (!Subtarget->hasNEON())
16478 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16479 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16480 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16485 LD->getMemoryVT(), LD->getMemOperand());
16496 EVT VT =
N->getValueType(0);
16511 SDValue StVal = St->getValue();
16513 if (!St->isTruncatingStore() || !VT.
isVector())
16516 EVT StVT = St->getMemoryVT();
16518 assert(StVT != VT &&
"Cannot truncate to the same type");
16528 if (0 != (NumElems * FromEltSz) % ToEltSz)
16531 unsigned SizeRatio = FromEltSz / ToEltSz;
16536 NumElems * SizeRatio);
16542 for (
unsigned i = 0; i < NumElems; ++i)
16556 MVT StoreType = MVT::i8;
16558 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16574 SDValue BasePtr = St->getBasePtr();
16578 for (
unsigned I = 0;
I <
E;
I++) {
16582 DAG.
getStore(St->getChain(),
DL, SubVec, BasePtr, St->getPointerInfo(),
16583 St->getAlign(), St->getMemOperand()->getFlags());
16596 if (!St->isSimple() || St->isTruncatingStore() || !St->isUnindexed())
16598 SDValue Trunc = St->getValue();
16609 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16612 unsigned NumElements = 4;
16629 unsigned Off0 = Rev ? NumElts : 0;
16630 unsigned Off1 = Rev ? 0 : NumElts;
16632 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16633 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16635 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16643 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16650 SDValue BasePtr = St->getBasePtr();
16651 Align Alignment = St->getBaseAlign();
16663 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16674 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16677 Ch,
DL, Extract, NewPtr, St->getPointerInfo().getWithOffset(NewOffset),
16678 NewToVT, Alignment, MMOFlags, AAInfo);
16689 if (!St->isSimple() || St->isTruncatingStore() || !St->isUnindexed())
16691 SDValue Trunc = St->getValue();
16701 SDValue BasePtr = St->getBasePtr();
16702 Align Alignment = St->getBaseAlign();
16711 unsigned NewOffset =
16718 Ch,
DL, Extract, NewPtr, St->getPointerInfo().getWithOffset(NewOffset),
16719 NewToVT, Alignment, MMOFlags, AAInfo);
16730 if (!St->isSimple() || St->isTruncatingStore() || !St->isUnindexed())
16732 SDValue Extract = St->getValue();
16741 {Extract.getOperand(0), Extract.getOperand(1)});
16749 SDValue BasePtr = St->getBasePtr();
16750 Align Alignment = St->getBaseAlign();
16755 St->getPointerInfo(), NewToVT, Alignment,
16767 if (St->isVolatile())
16769 SDValue StVal = St->getValue();
16772 if (Subtarget->hasNEON())
16776 if (Subtarget->hasMVEFloatOps())
16780 if (Subtarget->hasMVEIntegerOps()) {
16797 SDValue BasePtr = St->getBasePtr();
16800 BasePtr, St->getPointerInfo(), St->getBaseAlign(),
16801 St->getMemOperand()->getFlags());
16807 St->getPointerInfo().getWithOffset(4),
16808 St->getBaseAlign(), St->getMemOperand()->
getFlags());
16830 return DAG.
getStore(St->getChain(), dl, V, St->getBasePtr(),
16831 St->getPointerInfo(), St->getAlign(),
16832 St->getMemOperand()->getFlags(), St->getAAInfo());
16854 if (!Subtarget->hasNEON())
16858 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16866 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16868 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16869 uint32_t IntBits = IntTy.getSizeInBits();
16870 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16871 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16882 if (
C == -1 ||
C == 0 ||
C > 32)
16887 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16888 Intrinsic::arm_neon_vcvtfp2fxu;
16891 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16894 if (IntBits < FloatBits)
16902 if (!Subtarget->hasMVEFloatOps())
16910 EVT VT =
N->getValueType(0);
16915 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16917 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
16919 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16920 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16922 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16935 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
16946 EVT VT =
N->getValueType(0);
16949 if (!
N->getFlags().hasAllowReassociation())
16956 unsigned Opc =
A.getConstantOperandVal(0);
16957 if (
Opc != Intrinsic::arm_mve_vcmlaq)
16962 A.getOperand(3),
A.getOperand(4));
16994 if (!Subtarget->hasNEON())
16998 unsigned OpOpcode =
Op.getNode()->getOpcode();
16999 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17003 SDValue ConstVec =
N->getOperand(1);
17007 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17009 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17010 uint32_t IntBits = IntTy.getSizeInBits();
17011 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17012 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17032 int32_t
C = IntVal.exactLogBase2();
17033 if (
C == -1 ||
C == 0 ||
C > 32)
17039 if (IntBits < FloatBits)
17041 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17043 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17044 : Intrinsic::arm_neon_vcvtfxu2fp;
17052 if (!ST->hasMVEIntegerOps())
17056 EVT ResVT =
N->getValueType(0);
17084 EVT AVT =
A.getValueType();
17090 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17091 EVT AVT =
A.getValueType();
17101 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17102 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17105 if (ExtTypeMatches(
A, ExtTypes))
17106 return ExtendIfNeeded(
A, ExtendCode);
17109 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17119 if (ExtTypeMatches(
A, ExtTypes))
17120 return ExtendIfNeeded(
A, ExtendCode);
17123 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17133 if (ResVT != RetTy)
17136 if (
Mul->getOpcode() == ExtendCode &&
17137 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17139 Mul =
Mul->getOperand(0);
17148 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17149 A = ExtendIfNeeded(
A, ExtendCode);
17150 B = ExtendIfNeeded(
B, ExtendCode);
17155 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17168 if (
Mul->getOpcode() == ExtendCode &&
17169 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17171 Mul =
Mul->getOperand(0);
17180 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17181 A = ExtendIfNeeded(
A, ExtendCode);
17182 B = ExtendIfNeeded(
B, ExtendCode);
17193 EVT VT =
Ops[0].getValueType();
17194 if (VT == MVT::v16i8) {
17195 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17196 "Unexpected illegal long reduction opcode");
17197 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17209 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17222 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17224 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17225 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17227 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17228 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17230 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17233 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17236 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17240 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17243 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17246 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17249 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17252 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17255 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17258 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17260 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17262 return Create64bitNode(ARMISD::VADDLVs, {
A});
17264 return Create64bitNode(ARMISD::VADDLVu, {
A});
17267 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17270 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17273 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17275 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17277 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17279 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17282 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17285 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17292 Op =
Op->getOperand(1);
17294 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17296 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17313 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17315 if (!Shuf || !Shuf->getOperand(1).isUndef())
17320 APInt SetElts(Mask.size(), 0);
17321 for (
int E : Mask) {
17329 if (
N->getNumOperands() != VecOp + 1) {
17331 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17337 if (
Op.getValueType().isVector())
17338 Ops.push_back(
Op.getOperand(0));
17349 unsigned IsTop =
N->getConstantOperandVal(2);
17356 if (Op0->
isUndef() && !IsTop)
17361 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17362 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17370 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17372 APInt Op0DemandedElts =
17373 IsTop ? Op1DemandedElts
17388 unsigned IsTop =
N->getConstantOperandVal(2);
17390 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17391 APInt Op0DemandedElts =
17403 EVT VT =
N->getValueType(0);
17410 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17411 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17415 LHS.getOperand(0),
RHS.getOperand(0));
17430 int ShiftAmt =
C->getSExtValue();
17431 if (ShiftAmt == 0) {
17437 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17438 unsigned NewOpcode =
17439 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17454 unsigned IntNo =
N->getConstantOperandVal(0);
17465 case Intrinsic::arm_neon_vshifts:
17466 case Intrinsic::arm_neon_vshiftu:
17467 case Intrinsic::arm_neon_vrshifts:
17468 case Intrinsic::arm_neon_vrshiftu:
17469 case Intrinsic::arm_neon_vrshiftn:
17470 case Intrinsic::arm_neon_vqshifts:
17471 case Intrinsic::arm_neon_vqshiftu:
17472 case Intrinsic::arm_neon_vqshiftsu:
17473 case Intrinsic::arm_neon_vqshiftns:
17474 case Intrinsic::arm_neon_vqshiftnu:
17475 case Intrinsic::arm_neon_vqshiftnsu:
17476 case Intrinsic::arm_neon_vqrshiftns:
17477 case Intrinsic::arm_neon_vqrshiftnu:
17478 case Intrinsic::arm_neon_vqrshiftnsu: {
17479 EVT VT =
N->getOperand(1).getValueType();
17481 unsigned VShiftOpc = 0;
17484 case Intrinsic::arm_neon_vshifts:
17485 case Intrinsic::arm_neon_vshiftu:
17487 VShiftOpc = ARMISD::VSHLIMM;
17490 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17491 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17492 : ARMISD::VSHRuIMM);
17497 case Intrinsic::arm_neon_vrshifts:
17498 case Intrinsic::arm_neon_vrshiftu:
17503 case Intrinsic::arm_neon_vqshifts:
17504 case Intrinsic::arm_neon_vqshiftu:
17509 case Intrinsic::arm_neon_vqshiftsu:
17514 case Intrinsic::arm_neon_vrshiftn:
17515 case Intrinsic::arm_neon_vqshiftns:
17516 case Intrinsic::arm_neon_vqshiftnu:
17517 case Intrinsic::arm_neon_vqshiftnsu:
17518 case Intrinsic::arm_neon_vqrshiftns:
17519 case Intrinsic::arm_neon_vqrshiftnu:
17520 case Intrinsic::arm_neon_vqrshiftnsu:
17532 case Intrinsic::arm_neon_vshifts:
17533 case Intrinsic::arm_neon_vshiftu:
17536 case Intrinsic::arm_neon_vrshifts:
17537 VShiftOpc = ARMISD::VRSHRsIMM;
17539 case Intrinsic::arm_neon_vrshiftu:
17540 VShiftOpc = ARMISD::VRSHRuIMM;
17542 case Intrinsic::arm_neon_vrshiftn:
17543 VShiftOpc = ARMISD::VRSHRNIMM;
17545 case Intrinsic::arm_neon_vqshifts:
17546 VShiftOpc = ARMISD::VQSHLsIMM;
17548 case Intrinsic::arm_neon_vqshiftu:
17549 VShiftOpc = ARMISD::VQSHLuIMM;
17551 case Intrinsic::arm_neon_vqshiftsu:
17552 VShiftOpc = ARMISD::VQSHLsuIMM;
17554 case Intrinsic::arm_neon_vqshiftns:
17555 VShiftOpc = ARMISD::VQSHRNsIMM;
17557 case Intrinsic::arm_neon_vqshiftnu:
17558 VShiftOpc = ARMISD::VQSHRNuIMM;
17560 case Intrinsic::arm_neon_vqshiftnsu:
17561 VShiftOpc = ARMISD::VQSHRNsuIMM;
17563 case Intrinsic::arm_neon_vqrshiftns:
17564 VShiftOpc = ARMISD::VQRSHRNsIMM;
17566 case Intrinsic::arm_neon_vqrshiftnu:
17567 VShiftOpc = ARMISD::VQRSHRNuIMM;
17569 case Intrinsic::arm_neon_vqrshiftnsu:
17570 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17575 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17576 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17579 case Intrinsic::arm_neon_vshiftins: {
17580 EVT VT =
N->getOperand(1).getValueType();
17582 unsigned VShiftOpc = 0;
17585 VShiftOpc = ARMISD::VSLIIMM;
17586 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17587 VShiftOpc = ARMISD::VSRIIMM;
17593 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17594 N->getOperand(1),
N->getOperand(2),
17598 case Intrinsic::arm_neon_vqrshifts:
17599 case Intrinsic::arm_neon_vqrshiftu:
17603 case Intrinsic::arm_neon_vbsl: {
17605 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17606 N->getOperand(2),
N->getOperand(3));
17608 case Intrinsic::arm_mve_vqdmlah:
17609 case Intrinsic::arm_mve_vqdmlash:
17610 case Intrinsic::arm_mve_vqrdmlah:
17611 case Intrinsic::arm_mve_vqrdmlash:
17612 case Intrinsic::arm_mve_vmla_n_predicated:
17613 case Intrinsic::arm_mve_vmlas_n_predicated:
17614 case Intrinsic::arm_mve_vqdmlah_predicated:
17615 case Intrinsic::arm_mve_vqdmlash_predicated:
17616 case Intrinsic::arm_mve_vqrdmlah_predicated:
17617 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17622 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17629 case Intrinsic::arm_mve_minv:
17630 case Intrinsic::arm_mve_maxv:
17631 case Intrinsic::arm_mve_minav:
17632 case Intrinsic::arm_mve_maxav:
17633 case Intrinsic::arm_mve_minv_predicated:
17634 case Intrinsic::arm_mve_maxv_predicated:
17635 case Intrinsic::arm_mve_minav_predicated:
17636 case Intrinsic::arm_mve_maxav_predicated: {
17639 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17646 case Intrinsic::arm_mve_addv: {
17649 bool Unsigned =
N->getConstantOperandVal(2);
17650 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17654 case Intrinsic::arm_mve_addlv:
17655 case Intrinsic::arm_mve_addlv_predicated: {
17658 bool Unsigned =
N->getConstantOperandVal(2);
17659 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17660 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17661 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17664 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17666 Ops.push_back(
N->getOperand(i));
17679 EVT VT =
Y.getValueType();
17682 if (Subtarget->hasMVEIntegerOps())
17684 if (Subtarget->hasNEON())
17698 EVT VT =
N->getValueType(0);
17700 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17701 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17702 N->getOperand(0)->hasOneUse()) {
17719 if (AndMask == 255 || AndMask == 65535)
17723 if (MaskedBits > ShiftAmt) {
17738 if (ST->hasMVEIntegerOps())
17743 switch (
N->getOpcode()) {
17749 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17756 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17757 unsigned VShiftOpc =
17758 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17760 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17776 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17779 EVT FromVT = LD->getValueType(0);
17780 EVT ToVT =
N->getValueType(0);
17787 unsigned NumElements = 0;
17788 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17790 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17792 if (NumElements == 0 ||
17802 SDValue BasePtr = LD->getBasePtr();
17803 Align Alignment = LD->getBaseAlign();
17824 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17825 Alignment, MMOFlags, AAInfo);
17831 if (FromEltVT == MVT::f16) {
17834 for (
unsigned i = 0; i < Loads.
size(); i++) {
17836 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
17855 EVT VT =
N->getValueType(0);
17862 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17869 if (VT == MVT::i32 &&
17870 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17875 switch (
N->getOpcode()) {
17878 Opc = ARMISD::VGETLANEs;
17882 Opc = ARMISD::VGETLANEu;
17889 if (ST->hasMVEIntegerOps())
17907 Ops.push_back(Ext);
17917 if (ST->hasMVEFloatOps())
17928 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17932 EVT VT =
Op.getValueType();
17935 if (VT != MVT::i32 ||
17951 APInt MaxC = Max.getConstantOperandAPInt(1);
17952 if (MaxC.
sgt(MinC))
17959 if ((MinC + 1).isPowerOf2()) {
17981 APInt Width = MinC - MaxC + 1;
17984 unsigned SatBit = Width.
logBase2() - 1;
18002 EVT VT =
N->getValueType(0);
18005 if (VT == MVT::i32)
18008 if (!ST->hasMVEIntegerOps())
18014 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18017 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18025 if (VT == MVT::v4i32)
18026 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18028 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18035 MaxC != ~SaturateC)
18040 if (IsSignedSaturate(
N, N0.
getNode())) {
18043 if (VT == MVT::v4i32) {
18044 HalfVT = MVT::v8i16;
18045 ExtVT = MVT::v4i16;
18047 HalfVT = MVT::v16i8;
18062 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18068 if (VT == MVT::v4i32)
18069 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18071 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18080 if (IsUnsignedSaturate(
N)) {
18084 if (VT == MVT::v4i32) {
18085 HalfVT = MVT::v8i16;
18086 ExtConst = 0x0000FFFF;
18088 HalfVT = MVT::v16i8;
18110 const APInt *CV = &
C->getAPIntValue();
18167 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18174 if ((OrCI &
Known.Zero) != OrCI)
18180 EVT VT =
X.getValueType();
18181 unsigned BitInX = AndC->
logBase2();
18189 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18190 BitInY < NumActiveBits; ++BitInY) {
18191 if (OrCI[BitInY] == 0)
18194 Mask.setBit(BitInY);
18195 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18211 switch (
N->getOpcode()) {
18226 if (Const->isZero())
18228 else if (Const->isOne())
18236 unsigned IntOp =
N.getConstantOperandVal(1);
18237 if (IntOp != Intrinsic::test_start_loop_iterations &&
18238 IntOp != Intrinsic::loop_decrement_reg)
18264 bool Negate =
false;
18270 Cond =
N->getOperand(1);
18271 Dest =
N->getOperand(2);
18275 Cond =
N->getOperand(2);
18276 Dest =
N->getOperand(4);
18278 if (!Const->isOne() && !Const->isZero())
18280 Imm = Const->getZExtValue();
18308 assert((IsTrueIfZero(CC,
Imm) || IsFalseIfZero(CC,
Imm)) &&
18309 "unsupported condition");
18314 unsigned IntOp =
Int->getConstantOperandVal(1);
18315 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18316 "expected single br user");
18317 SDNode *Br = *
N->user_begin();
18327 if (IntOp == Intrinsic::test_start_loop_iterations) {
18329 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18331 if (IsTrueIfZero(CC,
Imm)) {
18333 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18337 UpdateUncondBr(Br, Dest, DAG);
18339 SDValue Ops[] = {Chain, Setup, OtherTarget};
18340 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18352 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18360 if (
Target == OtherTarget)
18361 UpdateUncondBr(Br, Dest, DAG);
18367 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18376 if (Cmp.getOpcode() != ARMISD::CMPZ)
18381 SDValue LHS = Cmp.getOperand(0);
18382 SDValue RHS = Cmp.getOperand(1);
18391 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18392 LHS->getOperand(0)->hasOneUse() &&
18396 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18408 EVT VT =
N->getValueType(0);
18409 SDValue FalseVal =
N->getOperand(0);
18410 SDValue TrueVal =
N->getOperand(1);
18418 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18425 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18428 if (Cmp.getOpcode() != ARMISD::CMPZ)
18432 SDValue LHS = Cmp.getOperand(0);
18433 SDValue RHS = Cmp.getOperand(1);
18437 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18461 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18462 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18463 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18466 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18471 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18474 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18475 LHS->getOperand(2), LHS->getOperand(3));
18485 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18489 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18491 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18500 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18533 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18545 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18565 const APInt *TrueConst;
18566 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18567 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18568 FalseVal.getOperand(1) == RHS) ||
18572 unsigned ShiftAmount = TrueConst->
logBase2();
18587 if (
Known.Zero == 0xfffffffe)
18590 else if (
Known.Zero == 0xffffff00)
18593 else if (
Known.Zero == 0xffff0000)
18606 EVT DstVT =
N->getValueType(0);
18609 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18610 EVT SrcVT = Src.getValueType();
18612 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18617 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18618 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18619 Src.getValueType().getScalarSizeInBits())
18620 Src = Src.getOperand(0);
18624 EVT SrcVT = Src.getValueType();
18625 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18626 Src.getOpcode() == ARMISD::VMVNIMM ||
18627 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18630 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18644 EVT VT =
N->getValueType(0);
18652 if (
N->getNumOperands() == 2 &&
18656 N->getOperand(0).getOperand(1),
18657 N->getOperand(1).getOperand(0),
18658 N->getOperand(1).getOperand(1));
18661 if (
N->getNumOperands() == 2 &&
18667 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18668 S0->getOperand(1) ==
S1->getOperand(1)) {
18671 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18675 ARMISD::VMOVN,
DL, VT,
18676 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18677 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18681 ARMISD::VMOVN,
DL, VT,
18682 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18683 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18691 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18692 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18693 (Op.getOpcode() == ISD::BITCAST &&
18694 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18697 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18699 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18717 int NumIns =
N->getNumOperands();
18718 assert((NumIns == 2 || NumIns == 4) &&
18719 "Expected 2 or 4 inputs to an MVETrunc");
18721 if (
N->getNumOperands() == 4)
18725 for (
int I = 0;
I < NumIns;
I++) {
18727 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18732 Ptr, MPI, StoreVT,
Align(4));
18747 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18750 EVT FromVT = LD->getMemoryVT();
18751 EVT ToVT =
N->getValueType(0);
18758 unsigned NumElements = 0;
18759 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18761 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18763 assert(NumElements != 0);
18769 LD->getExtensionType() != NewExtType)
18776 SDValue BasePtr = LD->getBasePtr();
18777 Align Alignment = LD->getBaseAlign();
18796 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18797 Alignment, MMOFlags, AAInfo);
18813 EVT VT =
N->getValueType(0);
18815 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18816 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18818 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18820 auto Extend = [&](
SDValue V) {
18829 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
18830 SDValue Ext = Extend(
N->getOperand(0));
18838 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18839 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
18843 auto CheckInregMask = [&](
int Start,
int Offset) {
18845 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18851 if (CheckInregMask(0, 0))
18853 else if (CheckInregMask(0, 1))
18854 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18855 else if (CheckInregMask(0, Mask.size()))
18857 else if (CheckInregMask(0, Mask.size() + 1))
18858 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18863 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18867 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18869 if (V0.getNode() !=
N ||
V1.getNode() !=
N)
18874 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
18885 int NumOuts =
N->getNumValues();
18886 assert((NumOuts == 2 || NumOuts == 4) &&
18887 "Expected 2 or 4 outputs to an MVEEXT");
18888 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18890 if (
N->getNumOperands() == 4)
18896 StackPtr, MPI,
Align(4));
18899 for (
int I = 0;
I < NumOuts;
I++) {
18901 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18902 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18907 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
18916 switch (
N->getOpcode()) {
18976 case ARMISD::BRCOND:
18980 case ARMISD::CSINC:
18981 case ARMISD::CSINV:
18982 case ARMISD::CSNEG:
18995 case ARMISD::PREDICATE_CAST:
18997 case ARMISD::VECTOR_REG_CAST:
19008 case ARMISD::VADDVs:
19009 case ARMISD::VADDVu:
19010 case ARMISD::VADDLVs:
19011 case ARMISD::VADDLVu:
19012 case ARMISD::VADDLVAs:
19013 case ARMISD::VADDLVAu:
19014 case ARMISD::VMLAVs:
19015 case ARMISD::VMLAVu:
19016 case ARMISD::VMLALVs:
19017 case ARMISD::VMLALVu:
19018 case ARMISD::VMLALVAs:
19019 case ARMISD::VMLALVAu:
19021 case ARMISD::VMOVN:
19023 case ARMISD::VQMOVNs:
19024 case ARMISD::VQMOVNu:
19026 case ARMISD::VQDMULH:
19032 case ARMISD::SMULWB: {
19033 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19039 case ARMISD::SMULWT: {
19040 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19046 case ARMISD::SMLALBB:
19047 case ARMISD::QADD16b:
19048 case ARMISD::QSUB16b:
19049 case ARMISD::UQADD16b:
19050 case ARMISD::UQSUB16b: {
19051 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19058 case ARMISD::SMLALBT: {
19059 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19061 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19068 case ARMISD::SMLALTB: {
19069 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19071 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19078 case ARMISD::SMLALTT: {
19079 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19086 case ARMISD::QADD8b:
19087 case ARMISD::QSUB8b:
19088 case ARMISD::UQADD8b:
19089 case ARMISD::UQSUB8b: {
19090 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19098 if (
N->getOperand(1) ==
N->getOperand(2))
19099 return N->getOperand(1);
19103 switch (
N->getConstantOperandVal(1)) {
19104 case Intrinsic::arm_neon_vld1:
19105 case Intrinsic::arm_neon_vld1x2:
19106 case Intrinsic::arm_neon_vld1x3:
19107 case Intrinsic::arm_neon_vld1x4:
19108 case Intrinsic::arm_neon_vld2:
19109 case Intrinsic::arm_neon_vld3:
19110 case Intrinsic::arm_neon_vld4:
19111 case Intrinsic::arm_neon_vld2lane:
19112 case Intrinsic::arm_neon_vld3lane:
19113 case Intrinsic::arm_neon_vld4lane:
19114 case Intrinsic::arm_neon_vld2dup:
19115 case Intrinsic::arm_neon_vld3dup:
19116 case Intrinsic::arm_neon_vld4dup:
19117 case Intrinsic::arm_neon_vst1:
19118 case Intrinsic::arm_neon_vst1x2:
19119 case Intrinsic::arm_neon_vst1x3:
19120 case Intrinsic::arm_neon_vst1x4:
19121 case Intrinsic::arm_neon_vst2:
19122 case Intrinsic::arm_neon_vst3:
19123 case Intrinsic::arm_neon_vst4:
19124 case Intrinsic::arm_neon_vst2lane:
19125 case Intrinsic::arm_neon_vst3lane:
19126 case Intrinsic::arm_neon_vst4lane:
19128 case Intrinsic::arm_mve_vld2q:
19129 case Intrinsic::arm_mve_vld4q:
19130 case Intrinsic::arm_mve_vst2q:
19131 case Intrinsic::arm_mve_vst4q:
19148 unsigned *
Fast)
const {
19154 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19157 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19159 if (AllowsUnaligned) {
19161 *
Fast = Subtarget->hasV7Ops();
19166 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19170 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19177 if (!Subtarget->hasMVEIntegerOps())
19181 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19182 Ty == MVT::v2i1)) {
19190 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19206 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19207 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19208 Ty == MVT::v2f64) {
19221 if ((
Op.isMemcpyOrMemmove() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19222 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19224 if (
Op.size() >= 16 &&
19230 }
else if (
Op.size() >= 8 &&
19247 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19249 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19251 return (SrcBits == 64 && DestBits == 32);
19260 return (SrcBits == 64 && DestBits == 32);
19296 return Subtarget->hasFullFP16();
19303 if (!Subtarget->hasMVEIntegerOps())
19322 if (Ld->isExpandingLoad())
19326 if (Subtarget->hasMVEIntegerOps())
19339 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19371bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19373 if (Subtarget->useSoftFloat())
19382 return Subtarget->hasMVEFloatOps();
19400 unsigned Scale = 1;
19417 if ((V & (Scale - 1)) != 0)
19426 if (VT.
isVector() && Subtarget->hasNEON())
19429 !Subtarget->hasMVEFloatOps())
19432 bool IsNeg =
false;
19438 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19441 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19457 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19463 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19493 default:
return false;
19512 int Scale = AM.
Scale;
19517 default:
return false;
19525 Scale = Scale & ~1;
19526 return Scale == 2 || Scale == 4 || Scale == 8;
19543 if (Scale & 1)
return false;
19550 const int Scale = AM.
Scale;
19560 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19576 switch (AM.
Scale) {
19587 if (Subtarget->isThumb1Only())
19590 if (Subtarget->isThumb2())
19593 int Scale = AM.
Scale;
19595 default:
return false;
19599 if (Scale < 0) Scale = -Scale;
19607 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19620 if (Scale & 1)
return false;
19633 if (!Subtarget->isThumb())
19636 if (Subtarget->isThumb2())
19640 return Imm >= 0 &&
Imm <= 255;
19650 if (!Subtarget->isThumb())
19652 if (Subtarget->isThumb2())
19655 return AbsImm <= 255;
19690 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19694 int RHSC = (int)
RHS->getZExtValue();
19695 if (RHSC < 0 && RHSC > -256) {
19705 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19708 int RHSC = (int)
RHS->getZExtValue();
19709 if (RHSC < 0 && RHSC > -0x1000) {
19751 int RHSC = (int)
RHS->getZExtValue();
19752 if (RHSC < 0 && RHSC > -0x100) {
19757 }
else if (RHSC > 0 && RHSC < 0x100) {
19768 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19779 bool CanChangeType = isLE && !IsMasked;
19782 int RHSC = (int)
RHS->getZExtValue();
19784 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19785 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19790 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19801 if (VT == MVT::v4i16) {
19802 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19804 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19805 if (IsInRange(RHSC, 0x80, 1))
19807 }
else if (Alignment >= 4 &&
19808 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19809 IsInRange(RHSC, 0x80, 4))
19811 else if (Alignment >= 2 &&
19812 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19813 IsInRange(RHSC, 0x80, 2))
19815 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19828 if (Subtarget->isThumb1Only())
19835 bool isSEXTLoad =
false;
19836 bool IsMasked =
false;
19838 Ptr = LD->getBasePtr();
19839 VT = LD->getMemoryVT();
19840 Alignment = LD->getAlign();
19841 AS = LD->getAddressSpace();
19844 Ptr = ST->getBasePtr();
19845 VT = ST->getMemoryVT();
19846 Alignment = ST->getAlign();
19847 AS = ST->getAddressSpace();
19849 Ptr = LD->getBasePtr();
19850 VT = LD->getMemoryVT();
19851 Alignment = LD->getAlign();
19852 AS = LD->getAddressSpace();
19856 Ptr = ST->getBasePtr();
19857 VT = ST->getMemoryVT();
19858 Alignment = ST->getAlign();
19859 AS = ST->getAddressSpace();
19874 bool isLegal =
false;
19876 isLegal = Subtarget->hasMVEIntegerOps() &&
19878 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19879 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19881 if (Subtarget->isThumb2())
19906 bool isSEXTLoad =
false, isNonExt;
19907 bool IsMasked =
false;
19909 VT = LD->getMemoryVT();
19910 Ptr = LD->getBasePtr();
19911 Alignment = LD->getAlign();
19915 VT = ST->getMemoryVT();
19916 Ptr = ST->getBasePtr();
19917 Alignment = ST->getAlign();
19918 isNonExt = !ST->isTruncatingStore();
19920 VT = LD->getMemoryVT();
19921 Ptr = LD->getBasePtr();
19922 Alignment = LD->getAlign();
19927 VT = ST->getMemoryVT();
19928 Ptr = ST->getBasePtr();
19929 Alignment = ST->getAlign();
19930 isNonExt = !ST->isTruncatingStore();
19935 if (Subtarget->isThumb1Only()) {
19938 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19939 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19942 if (!RHS || RHS->getZExtValue() != 4)
19944 if (Alignment <
Align(4))
19948 Base =
Op->getOperand(0);
19954 bool isLegal =
false;
19956 isLegal = Subtarget->hasMVEIntegerOps() &&
19961 if (Subtarget->isThumb2())
19975 !Subtarget->isThumb2())
19989 const APInt &DemandedElts,
19991 unsigned Depth)
const {
19994 switch (
Op.getOpcode()) {
20001 if (
Op.getResNo() == 0) {
20012 case ARMISD::CMOV: {
20015 if (
Known.isUnknown())
20027 case Intrinsic::arm_ldaex:
20028 case Intrinsic::arm_ldrex: {
20036 case ARMISD::BFI: {
20043 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20044 Known.Zero &= Mask;
20048 case ARMISD::VGETLANEs:
20049 case ARMISD::VGETLANEu: {
20050 const SDValue &SrcSV =
Op.getOperand(0);
20056 "VGETLANE index out of bounds");
20061 EVT VT =
Op.getValueType();
20067 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20075 case ARMISD::VMOVrh: {
20081 case ARMISD::CSINC:
20082 case ARMISD::CSINV:
20083 case ARMISD::CSNEG: {
20091 if (
Op.getOpcode() == ARMISD::CSINC)
20094 else if (
Op.getOpcode() == ARMISD::CSINV)
20096 else if (
Op.getOpcode() == ARMISD::CSNEG)
20103 case ARMISD::VORRIMM:
20104 case ARMISD::VBICIMM: {
20105 unsigned Encoded =
Op.getConstantOperandVal(1);
20106 unsigned DecEltBits = 0;
20109 unsigned EltBits =
Op.getScalarValueSizeInBits();
20110 if (EltBits != DecEltBits) {
20119 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20120 APInt Imm(DecEltBits, DecodedVal);
20131 if (!Subtarget->isThumb())
20148 if (
Imm == 0 ||
Imm == ~0U)
20151 unsigned Opc =
Op.getOpcode();
20153 EVT VT =
Op.getValueType();
20155 unsigned ShrunkImm =
Imm & Demanded;
20156 unsigned ExpandedImm =
Imm | ~Demanded;
20158 auto IsLegalImm = [ShrunkImm, ExpandedImm](
unsigned CandidateImm) ->
bool {
20159 return (ShrunkImm & CandidateImm) == ShrunkImm &&
20160 (~ExpandedImm & CandidateImm) == 0;
20162 auto UseImm = [
Imm,
Opc,
Op, VT, &TLO](
unsigned NewImm) ->
bool {
20174 if (ShrunkImm == 0) {
20175 ++NumOptimizedImms;
20176 return UseImm(ShrunkImm);
20182 if (ExpandedImm == ~0U) {
20183 ++NumOptimizedImms;
20184 return UseImm(ExpandedImm);
20192 if (IsLegalImm(0xFF)) {
20193 ++NumOptimizedImms;
20194 return UseImm(0xFF);
20197 if (IsLegalImm(0xFFFF)) {
20198 ++NumOptimizedImms;
20199 return UseImm(0xFFFF);
20213 ++NumOptimizedImms;
20214 return UseImm(ShrunkImm);
20222 if ((~ExpandedImm) < 256) {
20223 ++NumOptimizedImms;
20224 return UseImm(ExpandedImm);
20230 !Subtarget->hasV6Ops()) {
20231 ++NumOptimizedImms;
20232 return UseImm(ExpandedImm);
20251 EVT VT =
Op.getValueType();
20266 switch (
Op.getOpcode()) {
20277 unsigned Imm =
C->getZExtValue();
20284 unsigned Depth)
const {
20285 unsigned Opc =
Op.getOpcode();
20289 case ARMISD::LSRL: {
20293 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20295 unsigned ShAmt =
Op->getConstantOperandVal(2);
20305 case ARMISD::VBICIMM: {
20307 unsigned ModImm =
Op.getConstantOperandVal(1);
20308 unsigned EltBits = 0;
20310 if ((OriginalDemandedBits & Mask) == 0)
20316 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
20331 if (!Subtarget->hasVFP2Base())
20335 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20347 unsigned S = Constraint.
size();
20349 switch (Constraint[0]) {
20361 }
else if (S == 2) {
20362 switch (Constraint[0]) {
20379 Value *CallOperandVal =
info.CallOperandVal;
20382 if (!CallOperandVal)
20386 switch (*constraint) {
20392 if (Subtarget->isThumb())
20407 if (PR == 0 || VT == MVT::Other)
20409 if (ARM::SPRRegClass.
contains(PR))
20410 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20411 if (ARM::DPRRegClass.
contains(PR))
20416using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20420 switch (Constraint.
size()) {
20423 switch (Constraint[0]) {
20425 if (Subtarget->isThumb())
20426 return RCPair(0U, &ARM::tGPRRegClass);
20427 return RCPair(0U, &ARM::GPRRegClass);
20429 if (Subtarget->isThumb())
20430 return RCPair(0U, &ARM::hGPRRegClass);
20433 if (Subtarget->isThumb1Only())
20434 return RCPair(0U, &ARM::tGPRRegClass);
20435 return RCPair(0U, &ARM::GPRRegClass);
20437 if (VT == MVT::Other)
20439 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20440 return RCPair(0U, &ARM::SPRRegClass);
20442 return RCPair(0U, &ARM::DPRRegClass);
20444 return RCPair(0U, &ARM::QPRRegClass);
20447 if (VT == MVT::Other)
20449 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20450 return RCPair(0U, &ARM::SPR_8RegClass);
20452 return RCPair(0U, &ARM::DPR_8RegClass);
20454 return RCPair(0U, &ARM::QPR_8RegClass);
20457 if (VT == MVT::Other)
20459 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20460 return RCPair(0U, &ARM::SPRRegClass);
20462 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20464 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20470 if (Constraint[0] ==
'T') {
20471 switch (Constraint[1]) {
20475 return RCPair(0U, &ARM::tGPREvenRegClass);
20477 return RCPair(0U, &ARM::tGPROddRegClass);
20486 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20487 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20490 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20491 Constraint =
"{lr}";
20495 return {0,
nullptr};
20503 std::vector<SDValue> &
Ops,
20508 if (Constraint.
size() != 1)
20511 char ConstraintLetter = Constraint[0];
20512 switch (ConstraintLetter) {
20515 case 'I':
case 'J':
case 'K':
case 'L':
20516 case 'M':
case 'N':
case 'O':
20521 int64_t CVal64 =
C->getSExtValue();
20522 int CVal = (int) CVal64;
20525 if (CVal != CVal64)
20528 switch (ConstraintLetter) {
20532 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20533 if (CVal >= 0 && CVal <= 65535)
20537 if (Subtarget->isThumb1Only()) {
20540 if (CVal >= 0 && CVal <= 255)
20542 }
else if (Subtarget->isThumb2()) {
20556 if (Subtarget->isThumb1Only()) {
20561 if (CVal >= -255 && CVal <= -1)
20567 if (CVal >= -4095 && CVal <= 4095)
20573 if (Subtarget->isThumb1Only()) {
20580 }
else if (Subtarget->isThumb2()) {
20600 if (Subtarget->isThumb1Only()) {
20603 if (CVal >= -7 && CVal < 7)
20605 }
else if (Subtarget->isThumb2()) {
20625 if (Subtarget->isThumb1Only()) {
20628 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20634 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20640 if (Subtarget->isThumb1Only()) {
20642 if (CVal >= 0 && CVal <= 31)
20648 if (Subtarget->isThumb1Only()) {
20651 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20660 if (Result.getNode()) {
20661 Ops.push_back(Result);
20671 "Unhandled Opcode in getDivRemLibcall");
20677 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20678 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20679 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20680 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20687 const AttributeList &FuncAttrs, RTLIB::LibcallImpl LCImpl) {
20690 "Unhandled Opcode in getDivRemArgList");
20691 SDValue Ops[2] = {
N->getOperand(0),
N->getOperand(1)};
20695 case RTLIB::impl___rt_sdiv:
20696 case RTLIB::impl___rt_udiv:
20697 case RTLIB::impl___rt_sdiv64:
20698 case RTLIB::impl___rt_udiv64:
20709 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20710 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20711 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20712 "Register-based DivRem lowering only");
20713 unsigned Opcode =
Op->getOpcode();
20715 "Invalid opcode for Div/Rem lowering");
20717 EVT VT =
Op->getValueType(0);
20737 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20738 : Subtarget->hasDivideInARMMode();
20739 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20740 Op->getSimpleValueType(0) == MVT::i32) {
20742 const SDValue Dividend =
Op->getOperand(0);
20743 const SDValue Divisor =
Op->getOperand(1);
20744 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20748 SDValue
Values[2] = {Div, Rem};
20755 if (LCImpl == RTLIB::Unsupported)
20758 auto [FuncTy, FuncAttrs] =
20762 Type *RetTy = FuncTy->getReturnType();
20772 if (
getTM().getTargetTriple().isOSWindows())
20775 TargetLowering::CallLoweringInfo CLI(DAG);
20779 Callee, std::move(Args))
20784 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20785 return CallInfo.first;
20791 EVT VT =
N->getValueType(0);
20797 Result[0], Result[1]);
20803 if (LCImpl == RTLIB::Unsupported)
20806 auto [FuncTy, FuncAttrs] =
20810 Type *RetTy = FuncTy->getReturnType();
20820 if (
getTM().getTargetTriple().isOSWindows())
20827 Callee, std::move(Args))
20831 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20834 SDNode *ResNode = CallResult.first.getNode();
20841 assert(
getTM().getTargetTriple().isOSWindows() &&
20842 "unsupported target platform");
20846 SDValue Chain =
Op.getOperand(0);
20847 SDValue
Size =
Op.getOperand(1);
20850 "no-stack-arg-probe")) {
20854 Chain =
SP.getValue(1);
20860 SDValue
Ops[2] = {
SP, Chain };
20871 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20872 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
20877 SDValue
Ops[2] = { NewSP, Chain };
20882 bool IsStrict =
Op->isStrictFPOpcode();
20883 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20884 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20886 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20887 "Unexpected type for custom-lowering FP_EXTEND");
20889 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20890 "With both FP DP and 16, any FP conversion is legal!");
20892 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20893 "With FP16, 16 to 32 conversion is legal!");
20896 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20901 Loc,
Op.getValueType(), SrcVal);
20915 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
20916 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20917 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20918 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20919 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20923 {DstVT, MVT::Other}, {Chain, SrcVal});
20930 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20931 "Unexpected type for custom-lowering FP_EXTEND");
20932 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20937 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20941 bool IsStrict =
Op->isStrictFPOpcode();
20943 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20945 EVT DstVT =
Op.getValueType();
20947 if (DstVT == MVT::bf16) {
20948 if (Subtarget->hasBF16() && SrcVT == MVT::f32)
20953 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20956 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20957 "Unexpected type for custom-lowering FP_ROUND");
20959 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20960 "With both FP DP and 16, any FP conversion is legal!");
20965 if (SrcSz == 32 && Subtarget->hasFP16())
20970 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20971 "Unexpected type for custom-lowering FP_ROUND");
20973 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
20975 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20987 if (v == 0xffffffff)
20999 bool ForCodeSize)
const {
21000 if (!Subtarget->hasVFP3Base())
21002 if (VT == MVT::f16 && Subtarget->hasFullFP16())
21004 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
21007 if (VT == MVT::f32)
21009 if (VT == MVT::f64 && Subtarget->hasFP64())
21022 case Intrinsic::arm_neon_vld1:
21023 case Intrinsic::arm_neon_vld2:
21024 case Intrinsic::arm_neon_vld3:
21025 case Intrinsic::arm_neon_vld4:
21026 case Intrinsic::arm_neon_vld2lane:
21027 case Intrinsic::arm_neon_vld3lane:
21028 case Intrinsic::arm_neon_vld4lane:
21029 case Intrinsic::arm_neon_vld2dup:
21030 case Intrinsic::arm_neon_vld3dup:
21031 case Intrinsic::arm_neon_vld4dup: {
21034 auto &
DL =
I.getDataLayout();
21035 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21037 Info.ptrVal =
I.getArgOperand(0);
21039 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21046 case Intrinsic::arm_neon_vld1x2:
21047 case Intrinsic::arm_neon_vld1x3:
21048 case Intrinsic::arm_neon_vld1x4: {
21051 auto &
DL =
I.getDataLayout();
21052 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21054 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
21056 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
21062 case Intrinsic::arm_neon_vst1:
21063 case Intrinsic::arm_neon_vst2:
21064 case Intrinsic::arm_neon_vst3:
21065 case Intrinsic::arm_neon_vst4:
21066 case Intrinsic::arm_neon_vst2lane:
21067 case Intrinsic::arm_neon_vst3lane:
21068 case Intrinsic::arm_neon_vst4lane: {
21071 auto &
DL =
I.getDataLayout();
21072 unsigned NumElts = 0;
21073 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21074 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21077 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21080 Info.ptrVal =
I.getArgOperand(0);
21082 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21089 case Intrinsic::arm_neon_vst1x2:
21090 case Intrinsic::arm_neon_vst1x3:
21091 case Intrinsic::arm_neon_vst1x4: {
21094 auto &
DL =
I.getDataLayout();
21095 unsigned NumElts = 0;
21096 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21097 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21100 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21103 Info.ptrVal =
I.getArgOperand(0);
21105 Info.align =
I.getParamAlign(0).valueOrOne();
21111 case Intrinsic::arm_mve_vld2q:
21112 case Intrinsic::arm_mve_vld4q: {
21116 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21118 Info.ptrVal =
I.getArgOperand(0);
21126 case Intrinsic::arm_mve_vst2q:
21127 case Intrinsic::arm_mve_vst4q: {
21130 Type *VecTy =
I.getArgOperand(1)->getType();
21131 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21133 Info.ptrVal =
I.getArgOperand(0);
21141 case Intrinsic::arm_mve_vldr_gather_base:
21142 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21144 Info.ptrVal =
nullptr;
21146 Info.align =
Align(1);
21151 case Intrinsic::arm_mve_vldr_gather_base_wb:
21152 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21154 Info.ptrVal =
nullptr;
21155 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21156 Info.align =
Align(1);
21161 case Intrinsic::arm_mve_vldr_gather_offset:
21162 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21164 Info.ptrVal =
nullptr;
21169 Info.align =
Align(1);
21174 case Intrinsic::arm_mve_vstr_scatter_base:
21175 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21177 Info.ptrVal =
nullptr;
21178 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21179 Info.align =
Align(1);
21184 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21185 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21187 Info.ptrVal =
nullptr;
21188 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21189 Info.align =
Align(1);
21194 case Intrinsic::arm_mve_vstr_scatter_offset:
21195 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21197 Info.ptrVal =
nullptr;
21202 Info.align =
Align(1);
21207 case Intrinsic::arm_ldaex:
21208 case Intrinsic::arm_ldrex: {
21209 auto &
DL =
I.getDataLayout();
21210 Type *ValTy =
I.getParamElementType(0);
21213 Info.ptrVal =
I.getArgOperand(0);
21215 Info.align =
DL.getABITypeAlign(ValTy);
21220 case Intrinsic::arm_stlex:
21221 case Intrinsic::arm_strex: {
21222 auto &
DL =
I.getDataLayout();
21223 Type *ValTy =
I.getParamElementType(1);
21226 Info.ptrVal =
I.getArgOperand(1);
21228 Info.align =
DL.getABITypeAlign(ValTy);
21233 case Intrinsic::arm_stlexd:
21234 case Intrinsic::arm_strexd:
21236 Info.memVT = MVT::i64;
21237 Info.ptrVal =
I.getArgOperand(2);
21239 Info.align =
Align(8);
21244 case Intrinsic::arm_ldaexd:
21245 case Intrinsic::arm_ldrexd:
21247 Info.memVT = MVT::i64;
21248 Info.ptrVal =
I.getArgOperand(0);
21250 Info.align =
Align(8);
21264 assert(Ty->isIntegerTy());
21266 unsigned Bits = Ty->getPrimitiveSizeInBits();
21267 if (Bits == 0 || Bits > 32)
21274 unsigned Index)
const {
21286 if (!Subtarget->hasDataBarrier()) {
21290 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21291 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21292 Builder.getInt32(0), Builder.getInt32(7),
21293 Builder.getInt32(10), Builder.getInt32(5)};
21294 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_mcr,
args);
21303 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_dmb, CDomain);
21324 if (Subtarget->preferISHSTBarriers())
21357 bool has64BitAtomicStore;
21358 if (Subtarget->isMClass())
21359 has64BitAtomicStore =
false;
21360 else if (Subtarget->isThumb())
21361 has64BitAtomicStore = Subtarget->hasV7Ops();
21363 has64BitAtomicStore = Subtarget->hasV6Ops();
21365 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21379 bool has64BitAtomicLoad;
21380 if (Subtarget->isMClass())
21381 has64BitAtomicLoad =
false;
21382 else if (Subtarget->isThumb())
21383 has64BitAtomicLoad = Subtarget->hasV7Ops();
21385 has64BitAtomicLoad = Subtarget->hasV6Ops();
21401 if (Subtarget->isMClass())
21402 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21403 else if (Subtarget->isThumb())
21404 hasAtomicRMW = Subtarget->hasV7Ops();
21406 hasAtomicRMW = Subtarget->hasV6Ops();
21407 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21431 bool HasAtomicCmpXchg;
21432 if (Subtarget->isMClass())
21433 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21434 else if (Subtarget->isThumb())
21435 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21437 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21439 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21446 return InsertFencesForAtomic;
21451 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21457 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21458 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21460 RTLIB::LibcallImpl SecurityCookieVar =
21461 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21462 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21463 SecurityCookieVar != RTLIB::Unsupported) {
21474 F->addParamAttr(0, Attribute::AttrKind::InReg);
21481 unsigned &
Cost)
const {
21483 if (!Subtarget->hasNEON())
21512 unsigned Opcode =
Op.getOpcode();
21514 case ARMISD::VORRIMM:
21515 case ARMISD::VBICIMM:
21519 Op, DemandedElts, DAG, Kind, ConsiderFlags,
Depth);
21523 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21527 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21532 if (!Subtarget->hasV7Ops())
21538 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21540 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21548 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21557 Module *M = Builder.getModule();
21563 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21565 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21568 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21570 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21571 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21572 if (!Subtarget->isLittle())
21574 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21575 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21576 return Builder.CreateOr(
21577 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21581 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21582 CallInst *CI = Builder.CreateIntrinsicWithoutFolding(
Int, Tys, Addr);
21585 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21586 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21591 if (!Subtarget->hasV7Ops())
21593 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21599 Module *M = Builder.getModule();
21607 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21610 Value *
Lo = Builder.CreateTrunc(Val, Int32Ty,
"lo");
21611 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32), Int32Ty,
"hi");
21612 if (!Subtarget->isLittle())
21614 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21617 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21621 CallInst *CI = Builder.CreateCall(
21622 Strex, {Builder.CreateZExtOrBitCast(
21632 return Subtarget->isMClass();
21640 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21647 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21650 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21658 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21666 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21669 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21674 if (Subtarget->hasNEON() && VecSize == 64)
21676 return VecSize % 128 == 0;
21680 if (Subtarget->hasNEON())
21682 if (Subtarget->hasMVEIntegerOps())
21702 "Invalid interleave factor");
21703 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21705 "Unmatched number of shufflevectors and indices");
21710 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21713 Type *EltTy = VecTy->getElementType();
21716 Align Alignment = LI->getAlign();
21734 Value *BaseAddr = LI->getPointerOperand();
21736 if (NumLoads > 1) {
21740 VecTy->getNumElements() / NumLoads);
21746 if (Subtarget->hasNEON()) {
21747 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21748 Type *Tys[] = {VecTy, PtrTy};
21749 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21750 Intrinsic::arm_neon_vld3,
21751 Intrinsic::arm_neon_vld4};
21754 Ops.push_back(BaseAddr);
21755 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21757 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21760 assert((Factor == 2 || Factor == 4) &&
21761 "expected interleave factor of 2 or 4 for MVE");
21763 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21764 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21765 Type *Tys[] = {VecTy, PtrTy};
21768 Ops.push_back(BaseAddr);
21769 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21779 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21783 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21784 VecTy->getNumElements() * Factor);
21790 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21792 unsigned Index = Indices[i];
21794 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21798 SubVec = Builder.CreateIntToPtr(
21802 SubVecs[SV].push_back(SubVec);
21811 auto &SubVec = SubVecs[SVI];
21814 SVI->replaceAllUsesWith(WideVec);
21850 const APInt &GapMask)
const {
21852 "Invalid interleave factor");
21857 "Unexpected mask on store");
21860 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21862 unsigned LaneLen = VecTy->getNumElements() / Factor;
21863 Type *EltTy = VecTy->getElementType();
21867 Align Alignment =
SI->getAlign();
21884 Type *IntTy =
DL.getIntPtrType(EltTy);
21889 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21890 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21896 Value *BaseAddr =
SI->getPointerOperand();
21898 if (NumStores > 1) {
21901 LaneLen /= NumStores;
21911 if (Subtarget->hasNEON()) {
21912 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21913 Intrinsic::arm_neon_vst3,
21914 Intrinsic::arm_neon_vst4};
21915 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21916 Type *Tys[] = {PtrTy, SubVecTy};
21919 Ops.push_back(BaseAddr);
21921 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21922 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21924 assert((Factor == 2 || Factor == 4) &&
21925 "expected interleave factor of 2 or 4 for MVE");
21927 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21928 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21929 Type *Tys[] = {PtrTy, SubVecTy};
21932 Ops.push_back(BaseAddr);
21934 for (
unsigned F = 0;
F < Factor;
F++) {
21935 Ops.push_back(Builder.getInt32(
F));
21936 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21942 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21945 if (StoreCount > 0)
21946 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21947 BaseAddr, LaneLen * Factor);
21952 for (
unsigned i = 0; i < Factor; i++) {
21953 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21954 if (Mask[IdxI] >= 0) {
21955 Shuffles.
push_back(Builder.CreateShuffleVector(
21958 unsigned StartMask = 0;
21959 for (
unsigned j = 1; j < LaneLen; j++) {
21960 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21961 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21962 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21972 Shuffles.
push_back(Builder.CreateShuffleVector(
21993 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21997 Members += SubMembers;
22003 Members += SubMembers * AT->getNumElements();
22004 }
else if (Ty->isFloatTy()) {
22009 }
else if (Ty->isDoubleTy()) {
22021 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
22023 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
22025 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
22038 return (Members > 0 && Members <= 4);
22044 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
22046 return ABITypeAlign;
22051 assert(StackAlign &&
"data layout string is missing stack alignment");
22052 return std::min(ABITypeAlign, *StackAlign);
22066 uint64_t Members = 0;
22070 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
22071 return IsHA || IsIntArray;
22094void ARMTargetLowering::insertCopiesSplitCSR(
22098 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22108 RC = &ARM::GPRRegClass;
22109 else if (ARM::DPRRegClass.
contains(*
I))
22110 RC = &ARM::DPRRegClass;
22120 assert(Entry->getParent()->getFunction().hasFnAttribute(
22121 Attribute::NoUnwind) &&
22122 "Function should be nounwind in insertCopiesSplitCSR!");
22123 Entry->addLiveIn(*
I);
22128 for (
auto *Exit : Exits)
22130 TII->get(TargetOpcode::COPY), *
I)
22141 return Subtarget->hasMVEIntegerOps();
22151 unsigned NumElements = VTy->getNumElements();
22158 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22159 return Subtarget->hasMVEFloatOps();
22164 return Subtarget->hasMVEIntegerOps() &&
22165 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22166 ScalarTy->isIntegerTy(32));
22170 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22181 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22183 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22185 if (TyWidth > 128) {
22186 int Stride = Ty->getNumElements() / 2;
22190 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22192 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22193 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22194 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22195 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22196 Value *LowerSplitAcc =
nullptr;
22197 Value *UpperSplitAcc =
nullptr;
22200 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22201 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22205 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22207 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22209 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22210 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22217 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22220 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22222 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22223 {ConstRotation, InputB, InputA});
22228 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22231 ConstRotation = ConstantInt::get(IntTy, 0);
22233 ConstRotation = ConstantInt::get(IntTy, 1);
22235 if (!ConstRotation)
22238 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22239 {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)
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 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 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 TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, FunctionType *FuncTy, const AttributeList &FuncAttrs, RTLIB::LibcallImpl LCImpl)
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 SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
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 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 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 GeneratePerfectShuffle(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...
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 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 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.
arm ldst static false bool definesCPSR(const MachineInstr &MI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static constexpr roundingMode rmTowardZero
LLVM_ABI bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
unsigned logBase2() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool isOne() const
Determine if this is a value of 1.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
const ARMBaseRegisterInfo & getRegisterInfo() const
const uint32_t * getSjLjDispatchPreservedMask(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const uint32_t * getTLSCallPreservedMask(const MachineFunction &MF) const
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj, ARMCP::ARMCPModifier Modifier=ARMCP::no_modifier, bool AddCurrentAddress=false)
ARMConstantPoolValue - ARM specific constantpool value.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
int getVarArgsFrameIndex() const
int getPromotedConstpoolIncrease() const
SmallPtrSet< const GlobalVariable *, 2 > & getGlobalsPromotedToConstantPool()
void setArgumentStackToRestore(unsigned v)
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
void setPromotedConstpoolIncrease(int Sz)
bool isThumb1OnlyFunction() const
void setArgRegsSaveSize(unsigned s)
bool isCmseNSEntryFunction() const
void setReturnRegsCount(unsigned s)
void setVarArgsFrameIndex(int Index)
unsigned getArgRegsSaveSize() const
void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV)
Indicate to the backend that GV has had its storage changed to inside a constant pool.
void setIsSplitCSR(bool s)
void setArgumentStackSize(unsigned size)
unsigned getArgumentStackSize() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool isReadOnly(const GlobalValue *GV) const
unsigned getMaxSupportedInterleaveFactor() const override
Get the maximum supported factor for interleaved memory accesses.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
unsigned getNumInterleavedAccesses(VectorType *VecTy, const DataLayout &DL) const
Returns the number of interleaved accesses that will be generated when lowering accesses of the given...
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Align getABIAlignmentForCallingConv(Type *ArgTy, const DataLayout &DL) const override
Return the correct alignment for the current calling convention.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
bool shouldFoldConstantShiftPairToMask(const SDNode *N) const override
Return true if it is profitable to fold a pair of shifts into a mask.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override
Return true if it is profitable to combine an XOR of a logical shift to create a logical shift of NOT...
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const
PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
Value * createComplexDeinterleavingIR(IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, Value *Accumulator=nullptr) const override
Create the IR node for the given complex deinterleaving operation.
bool isComplexDeinterleavingSupported() const override
Does this target support complex deinterleaving.
SDValue PerformMVEExtCombine(SDNode *N, DAGCombinerInfo &DCI) const
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const override
Inserts necessary declarations for SSP (stack protection) purpose.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &OriginalDemandedBits, const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the value type to use for ISD::SETCC.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const override
Perform a store-conditional operation to Addr.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool isVarArg) const
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
isShuffleMaskLegal - Targets can use this to indicate that they only support some VECTOR_SHUFFLE oper...
Register getExceptionPointerRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
bool lowerInterleavedStore(Instruction *Store, Value *Mask, ShuffleVectorInst *SVI, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved store into a vstN intrinsic.
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
bool useLoadStackGuardNode(const Module &M) const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vldN intrinsic.
std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override
Return the largest legal super-reg register class of the register class for the specified type and it...
bool preferSelectsOverBooleanArithmetic(EVT VT) const override
Should we prefer selects to doing arithmetic on boolean types.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
Register getExceptionSelectorRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of EXTRACT_SUBVECTOR for this result type with this index.
CallingConv::ID getEffectiveCallingConv(CallingConv::ID CC, bool isVarArg) const
getEffectiveCallingConv - Get the effective calling convention, taking into account presence of float...
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
bool supportKCFIBundles() const override
Return true if the target supports kcfi operand bundles.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool isVarArg) const
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
allowsMisalignedMemoryAccesses - Returns true if the target allows unaligned memory accesses of the s...
bool isLegalInterleavedAccessType(unsigned Factor, FixedVectorType *VecTy, Align Alignment, const DataLayout &DL) const
Returns true if VecTy is a legal interleaved access type.
bool isVectorLoadExtDesirable(SDValue ExtVal) const override
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, unsigned &Cost) const override
Return true if the target can combine store(extractelement VectorTy,Idx).
bool useSoftFloat() const override
bool alignLoopsWithOptSize() const override
Should loops be aligned even when the function is marked OptSize (but not MinSize).
SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const
bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override
Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail ...
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
bool hasAndNotCompare(SDValue V) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT.
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
bool isFloatingPointOperation() const
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
The address of a basic block.
static constexpr BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
LLVM_ABI int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, uint32_t BitWidth) const
If this is a constant FP splat and the splatted constant FP is an exact power or 2,...
CCState - This class holds information needed while lowering arguments and return values.
void getInRegsParamInfo(unsigned InRegsParamRecordIndex, unsigned &BeginReg, unsigned &EndReg) const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
void rewindByValRegsInfo()
unsigned getInRegsParamsProcessed() const
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd)
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
unsigned getInRegsParamsCount() const
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
const APFloat & getValueAPF() const
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
MachineConstantPoolValue * getMachineCPVal() const
bool isMachineConstantPoolEntry() const
const Constant * getConstVal() const
LLVM_ABI Type * getType() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
MaybeAlign getStackAlignment() const
Returns the natural stack alignment, or MaybeAlign() if one wasn't specified.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
StringRef getInternalSymbolPrefix() const
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
Tracks which library functions to use for a particular subtarget or function.
const RTLIB::RuntimeLibcallsInfo & getRuntimeLibcallsInfo() const
CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const
Get the CallingConv that should be used for the specified libcall.
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Describe properties that are true of each instruction in the target description file.
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
bool is64BitVector() const
Return true if this is a 64-bit vector type.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) 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.
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.
void setIsDead(bool Val=true)
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.
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 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.
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
const LibcallLoweringInfo & getLibcalls() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI OverflowKind computeOverflowForSignedAdd(SDValue N0, SDValue N1) const
Determine if the result of the signed addition of 2 nodes can overflow.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
This instruction constructs a fixed permutation of two input vectors.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
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
TargetInstrInfo - Interface to description of machine instruction set.
Provides information about what library functions are available for the current target.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
ShiftLegalizationStrategy
Return the preferred strategy to legalize tihs SHIFT instruction, with ExpansionFactor being the recu...
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
const TargetMachine & getTargetMachine() const
virtual void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const
Inserts necessary declarations for SSP (stack protection) purpose.
void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked load does or does not work with the specified type and ind...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked store does or does not work with the specified type and in...
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
static StringRef getLibcallImplName(RTLIB::LibcallImpl Call)
Get the libcall routine name for the specified libcall implementation.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool expandDIVREMByConstant(SDNode *N, SmallVectorImpl< SDValue > &Result, EVT HiLoVT, SelectionDAG &DAG, SDValue LL=SDValue(), SDValue LH=SDValue()) const
Attempt to expand an n-bit div/rem/divrem by constant using an n/2-bit algorithm.
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
static ArgListTy getArgListForFunctionType(FunctionType *FuncTy, const AttributeList &FuncAttrs, ArrayRef< SDValue > Ops)
Build a call argument list for FuncTy, taking the argument node values from Ops and the parameter typ...
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual ArrayRef< MCPhysReg > getRoundingControlRegisters() const
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
void setTypeIdForCallsiteInfo(const CallBase *CB, MachineFunction &MF, MachineFunction::CallSiteInfo &CSInfo) const
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
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)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
Base class of all SIMD vector types.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static CondCodes getOppositeCondition(CondCodes CC)
static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC)
getSwappedCondition - assume the flags are set by MI(a,b), return the condition code if we modify the...
@ SECREL
Thread Pointer Offset.
@ GOT_PREL
Thread Local Storage (General Dynamic Mode)
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
TOF
Target Operand Flag enum.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2Offset(unsigned AM2Opc)
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
AddrOpc getAM2Op(unsigned AM2Opc)
bool isBitFieldInvertedMask(unsigned v)
const unsigned FPStatusBits
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
const unsigned FPReservedBits
const unsigned RoundingBitsPos
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Swift
Calling convention for Swift.
@ ARM_APCS
ARM Procedure Calling Standard (obsolete, but still used on some targets).
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ ARM_AAPCS
ARM Architecture Procedure Calling Standard calling convention (aka EABI).
@ CXX_FAST_TLS
Used for access functions.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ ARM_AAPCS_VFP
Same as ARM_AAPCS, but uses hard floating point ABI.
@ C
The default llvm calling convention, compatible with C.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ POISON
POISON - A poison node.
@ SET_FPENV
Sets the current floating-point environment.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
@ FGETSIGN
INT = FGETSIGN(FP) - Return the sign bit of the specified floating point value as an integer 0/1 valu...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ RESET_FPENV
Set floating-point environment to default state.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SET_FPMODE
Sets the current dynamic floating-point control modes.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ EH_SJLJ_SETUP_DISPATCH
OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) The target initializes the dispatch table here.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ RESET_FPMODE
Sets default dynamic floating-point control modes.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ BR
Control flow instructions. These all have token chains.
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ BR_JT
BR_JT - Jumptable branch.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SMULO
Same for multiplication.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ SADDO_CARRY
Carry-using overflow-aware nodes for multiple precision addition and subtraction.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
void stable_sort(R &&Range)
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,...
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.
bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
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...
bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
const unsigned PerfectShuffleTable[6561+1]
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
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,...
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
@ SjLj
setjmp/longjmp based exceptions
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
UndefPoisonKind
Enumeration to track whether we are interested in Undef, Poison, or both.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
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,...
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.
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.
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.
LLVM_ABI std::pair< FunctionType *, AttributeList > getFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL, RTLIB::LibcallImpl LibcallImpl) const
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)