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;
7160 if (Mask.size() == Elements * 2)
7161 return Index / Elements;
7162 return Mask[Index] == 0 ? 0 : 1;
7192 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7200 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7202 for (
unsigned j = 0; j < NumElts; j += 2) {
7203 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7204 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7209 if (M.size() == NumElts*2)
7224 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7227 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7229 for (
unsigned j = 0; j < NumElts; j += 2) {
7230 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7231 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7236 if (M.size() == NumElts*2)
7256 if (M.size() != NumElts && M.size() != NumElts*2)
7259 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7261 for (
unsigned j = 0; j < NumElts; ++j) {
7262 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7267 if (M.size() == NumElts*2)
7286 if (M.size() != NumElts && M.size() != NumElts*2)
7289 unsigned Half = NumElts / 2;
7290 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7292 for (
unsigned j = 0; j < NumElts; j += Half) {
7293 unsigned Idx = WhichResult;
7294 for (
unsigned k = 0; k < Half; ++k) {
7295 int MIdx = M[i + j + k];
7296 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7303 if (M.size() == NumElts*2)
7327 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7330 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7332 unsigned Idx = WhichResult * NumElts / 2;
7333 for (
unsigned j = 0; j < NumElts; j += 2) {
7334 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7335 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7341 if (M.size() == NumElts*2)
7360 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7363 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7365 unsigned Idx = WhichResult * NumElts / 2;
7366 for (
unsigned j = 0; j < NumElts; j += 2) {
7367 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7368 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7374 if (M.size() == NumElts*2)
7387 unsigned &WhichResult,
7390 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7391 return ARMISD::VTRN;
7392 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7393 return ARMISD::VUZP;
7394 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7395 return ARMISD::VZIP;
7399 return ARMISD::VTRN;
7401 return ARMISD::VUZP;
7403 return ARMISD::VZIP;
7412 if (NumElts != M.size())
7416 for (
unsigned i = 0; i != NumElts; ++i)
7417 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7426 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7434 int Ofs = Top ? 1 : 0;
7435 int Upper = SingleSource ? 0 : NumElts;
7436 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7437 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7439 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7448 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7457 unsigned Offset = Top ? 0 : 1;
7458 unsigned N = SingleSource ? 0 : NumElts;
7459 for (
unsigned i = 0; i < NumElts; i += 2) {
7460 if (M[i] >= 0 && M[i] != (
int)i)
7462 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7471 if (NumElts != M.size())
7479 unsigned Off0 = rev ? NumElts / 2 : 0;
7480 unsigned Off1 = rev ? 0 : NumElts / 2;
7481 for (
unsigned i = 0; i < NumElts; i += 2) {
7482 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7484 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7500 if (!ST->hasMVEFloatOps())
7505 if (VT != MVT::v8f16)
7526 for (
unsigned i = 1; i < 4; i++) {
7541 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7553 if (!ST->hasMVEFloatOps())
7558 if (VT != MVT::v4f32)
7574 for (
unsigned i = 1; i < 4; i++) {
7585 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7597 Val =
N->getAsZExtVal();
7599 if (ST->isThumb1Only()) {
7600 if (Val <= 255 || ~Val <= 255)
7612 EVT VT =
Op.getValueType();
7614 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7618 unsigned BitsPerBool;
7622 }
else if (NumElts == 4) {
7625 }
else if (NumElts == 8) {
7628 }
else if (NumElts == 16) {
7639 return U.get().isUndef() || U.get() == FirstOp;
7643 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7647 unsigned Bits32 = 0;
7648 for (
unsigned i = 0; i < NumElts; ++i) {
7652 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7654 Bits32 |= BoolMask << (i * BitsPerBool);
7660 for (
unsigned i = 0; i < NumElts; ++i) {
7673 if (!ST->hasMVEIntegerOps())
7677 EVT VT =
Op.getValueType();
7687 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7691 for (
unsigned I = 2;
I < NumElts;
I++) {
7707 switch (
N->getOpcode()) {
7718 return N->getOperand(1).getNode() ==
Op;
7720 switch (
N->getConstantOperandVal(0)) {
7721 case Intrinsic::arm_mve_add_predicated:
7722 case Intrinsic::arm_mve_mul_predicated:
7723 case Intrinsic::arm_mve_qadd_predicated:
7724 case Intrinsic::arm_mve_vhadd:
7725 case Intrinsic::arm_mve_hadd_predicated:
7726 case Intrinsic::arm_mve_vqdmulh:
7727 case Intrinsic::arm_mve_qdmulh_predicated:
7728 case Intrinsic::arm_mve_vqrdmulh:
7729 case Intrinsic::arm_mve_qrdmulh_predicated:
7730 case Intrinsic::arm_mve_vqdmull:
7731 case Intrinsic::arm_mve_vqdmull_predicated:
7733 case Intrinsic::arm_mve_sub_predicated:
7734 case Intrinsic::arm_mve_qsub_predicated:
7735 case Intrinsic::arm_mve_vhsub:
7736 case Intrinsic::arm_mve_hsub_predicated:
7737 return N->getOperand(2).getNode() ==
Op;
7752 EVT VT =
Op.getValueType();
7760 APInt SplatBits, SplatUndef;
7761 unsigned SplatBitSize;
7763 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7770 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7772 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7773 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7774 : SplatBitSize == 16 ? MVT::v8i16
7777 SDValue VDup = DAG.
getNode(ARMISD::VDUP, dl, DupVT, Const);
7778 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7781 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7782 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7787 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7790 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, Val);
7791 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7795 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7797 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7800 SDValue Vmov = DAG.
getNode(ARMISD::VMVNIMM, dl, VmovVT, Val);
7801 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7805 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7809 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7815 if (
ST->hasMVEIntegerOps() &&
7816 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7817 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7818 : SplatBitSize == 16 ? MVT::v8i16
7821 SDValue VDup = DAG.
getNode(ARMISD::VDUP, dl, DupVT, Const);
7822 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7835 bool isOnlyLowElement =
true;
7836 bool usesOnlyOneValue =
true;
7837 bool hasDominantValue =
false;
7842 DenseMap<SDValue, unsigned> ValueCounts;
7844 for (
unsigned i = 0; i < NumElts; ++i) {
7845 SDValue
V =
Op.getOperand(i);
7849 isOnlyLowElement =
false;
7853 unsigned &
Count = ValueCounts[
V];
7856 if (++
Count > (NumElts / 2)) {
7857 hasDominantValue =
true;
7861 if (ValueCounts.
size() != 1)
7862 usesOnlyOneValue =
false;
7863 if (!
Value.getNode() && !ValueCounts.
empty())
7866 if (ValueCounts.
empty())
7872 (VT != MVT::v8f16 ||
ST->hasFullFP16()))
7879 if (hasDominantValue && EltSize <= 32) {
7888 ConstantSDNode *constIndex;
7895 if (VT !=
Value->getOperand(0).getValueType()) {
7898 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7903 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7908 if (!usesOnlyOneValue) {
7911 for (
unsigned I = 0;
I < NumElts; ++
I) {
7916 Ops.push_back(
Op.getOperand(
I));
7926 assert(FVT == MVT::f32 || FVT == MVT::f16);
7927 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7928 for (
unsigned i = 0; i < NumElts; ++i)
7933 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7937 if (usesOnlyOneValue) {
7940 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7954 if (SDValue
shuffle = ReconstructShuffle(
Op, DAG))
7964 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7984 if (EltSize >= 32) {
7990 for (
unsigned i = 0; i < NumElts; ++i)
8003 (VT == MVT::v8f16 && !
ST->hasFullFP16())) {
8005 for (
unsigned i = 0 ; i < NumElts; ++i) {
8006 SDValue
V =
Op.getOperand(i);
8009 SDValue LaneIdx = DAG.
getConstant(i, dl, MVT::i32);
8024 EVT VT =
Op.getValueType();
8027 struct ShuffleSourceInfo {
8029 unsigned MinElt = std::numeric_limits<unsigned>::max();
8030 unsigned MaxElt = 0;
8040 int WindowScale = 1;
8042 ShuffleSourceInfo(SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8044 bool operator ==(SDValue OtherVec) {
return Vec == OtherVec; }
8050 for (
unsigned i = 0; i < NumElts; ++i) {
8051 SDValue
V =
Op.getOperand(i);
8065 SDValue SourceVec =
V.getOperand(0);
8067 if (Source == Sources.
end())
8071 unsigned EltNo =
V.getConstantOperandVal(1);
8078 if (Sources.
size() > 2)
8084 for (
auto &Source : Sources) {
8085 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8086 if (SrcEltTy.
bitsLT(SmallestEltTy))
8087 SmallestEltTy = SrcEltTy;
8089 unsigned ResMultiplier =
8097 for (
auto &Src : Sources) {
8098 EVT SrcVT = Src.ShuffleVec.getValueType();
8102 if (SrcVTSize == VTSize)
8111 if (SrcVTSize < VTSize) {
8112 if (2 * SrcVTSize != VTSize)
8118 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8122 if (SrcVTSize != 2 * VTSize)
8125 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8130 if (Src.MinElt >= NumSrcElts) {
8135 Src.WindowBase = -NumSrcElts;
8136 }
else if (Src.MaxElt < NumSrcElts) {
8150 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8153 Src.WindowBase = -Src.MinElt;
8160 for (
auto &Src : Sources) {
8161 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8162 if (SrcEltTy == SmallestEltTy)
8165 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8167 Src.WindowBase *= Src.WindowScale;
8172 for (
auto Src : Sources)
8173 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8180 SDValue
Entry =
Op.getOperand(i);
8181 if (
Entry.isUndef())
8190 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8193 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8197 int *LaneMask = &
Mask[i * ResMultiplier];
8199 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8200 ExtractBase += NumElts * (Src - Sources.begin());
8201 for (
int j = 0;
j < LanesDefined; ++
j)
8202 LaneMask[j] = ExtractBase + j;
8208 assert(Sources.size() <= 2 &&
"Too many sources!");
8211 for (
unsigned i = 0; i < Sources.size(); ++i)
8218 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8240 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8260 unsigned PFIndexes[4];
8261 for (
unsigned i = 0; i != 4; ++i) {
8265 PFIndexes[i] = M[i];
8269 unsigned PFTableIndex =
8270 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8272 unsigned Cost = (PFEntry >> 30);
8278 bool ReverseVEXT, isV_UNDEF;
8279 unsigned Imm, WhichResult;
8282 if (EltSize >= 32 ||
8289 else if (Subtarget->hasNEON() &&
8294 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8297 else if (Subtarget->hasMVEIntegerOps() &&
8301 else if (Subtarget->hasMVEIntegerOps() &&
8315 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8316 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8317 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8320 if (LHSID == (1*9+2)*9+3)
return LHS;
8321 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8335 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8338 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8341 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8346 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8351 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8378 for (
int I : ShuffleMask)
8382 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8,
V1,
8385 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8,
V1, V2,
8391 EVT VT =
Op.getValueType();
8393 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8394 "Expect an v8i16/v16i8 type");
8400 std::vector<int> NewMask;
8404 NewMask.push_back(i);
8434 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8444 if (VT != MVT::v16i1)
8445 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8460 EVT VT =
Op.getValueType();
8464 assert(ST->hasMVEIntegerOps() &&
8465 "No support for vector shuffle of boolean predicates");
8475 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8491 "Expected identical vector type in expanded i1 shuffle!");
8495 PredAsVector2, ShuffleMask);
8500 if (VT == MVT::v2i1) {
8501 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8504 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8506 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8517 EVT VT =
Op.getValueType();
8521 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8522 "Unexpected vector type");
8524 int QuarterSize = NumElts / 4;
8533 for (
int i = 0; i <
Length; i++) {
8534 if (ShuffleMask[Start + i] >= 0) {
8535 if (ShuffleMask[Start + i] %
Length != i)
8537 MovIdx = ShuffleMask[Start + i] /
Length;
8545 for (
int i = 1; i <
Length; i++) {
8546 if (ShuffleMask[Start + i] >= 0 &&
8547 (ShuffleMask[Start + i] /
Length != MovIdx ||
8548 ShuffleMask[Start + i] %
Length != i))
8554 for (
int Part = 0; Part < 4; ++Part) {
8556 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8570 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8575 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8577 for (
int Part = 0; Part < 4; ++Part)
8578 for (
int i = 0; i < QuarterSize; i++)
8580 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8582 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8585 for (
int Part = 0; Part < 4; ++Part)
8601 EVT VT =
Op.getValueType();
8613 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8617 if (Mask[i] != i + BaseOffset) {
8618 if (OffElement == -1)
8624 return NonUndef > 2 && OffElement != -1;
8628 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8630 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8641 ShuffleMask[OffElement] < (
int)NumElts ?
V1 : V2,
8652 EVT VT =
Op.getValueType();
8656 if (ST->hasMVEIntegerOps() && EltSize == 1)
8667 if (EltSize <= 32) {
8671 if (Lane == -1) Lane = 0;
8675 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8682 bool IsScalarToVector =
true;
8683 for (
unsigned i = 1, e =
V1.getNumOperands(); i != e; ++i)
8684 if (!
V1.getOperand(i).isUndef()) {
8685 IsScalarToVector =
false;
8688 if (IsScalarToVector)
8689 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8691 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
V1,
8695 bool ReverseVEXT =
false;
8697 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT,
Imm)) {
8700 return DAG.
getNode(ARMISD::VEXT, dl, VT,
V1, V2,
8705 return DAG.
getNode(ARMISD::VREV64, dl, VT,
V1);
8707 return DAG.
getNode(ARMISD::VREV32, dl, VT,
V1);
8709 return DAG.
getNode(ARMISD::VREV16, dl, VT,
V1);
8721 unsigned WhichResult = 0;
8722 bool isV_UNDEF =
false;
8723 if (ST->hasNEON()) {
8725 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8732 if (ST->hasMVEIntegerOps()) {
8734 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2,
V1,
8737 return DAG.
getNode(ARMISD::VMOVN, dl, VT,
V1, V2,
8767 }) &&
"Unexpected shuffle index into UNDEF operand!");
8770 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8773 assert((WhichResult == 0) &&
8774 "In-place shuffle of concat can only have one result!");
8783 if (ST->hasMVEIntegerOps() && EltSize <= 32 &&
8784 (ST->hasFullFP16() || VT != MVT::v8f16)) {
8788 for (
bool Top : {
false,
true}) {
8789 for (
bool SingleSource : {
false,
true}) {
8790 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8795 SingleSource ?
V1 : V2);
8811 unsigned PFIndexes[4];
8812 for (
unsigned i = 0; i != 4; ++i) {
8813 if (ShuffleMask[i] < 0)
8816 PFIndexes[i] = ShuffleMask[i];
8820 unsigned PFTableIndex =
8821 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8823 unsigned Cost = (PFEntry >> 30);
8829 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8830 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8840 if (EltSize >= 32) {
8848 for (
unsigned i = 0; i < NumElts; ++i) {
8849 if (ShuffleMask[i] < 0)
8853 ShuffleMask[i] < (
int)NumElts ?
V1 : V2,
8861 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8865 if (ST->hasNEON() && VT == MVT::v8i8)
8869 if (ST->hasMVEIntegerOps())
8874 if (VT == MVT::v8f16 && !ST->hasFullFP16()) {
8876 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(0));
8878 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(1));
8880 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuf);
8888 EVT VecVT =
Op.getOperand(0).getValueType();
8891 assert(ST->hasMVEIntegerOps() &&
8892 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8895 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8896 unsigned Lane =
Op.getConstantOperandVal(2);
8897 unsigned LaneWidth =
8899 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8904 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8910 SDValue Lane =
Op.getOperand(2);
8914 SDValue Elt =
Op.getOperand(1);
8917 if (Subtarget->hasMVEIntegerOps() &&
8918 Op.getValueType().getScalarSizeInBits() == 1)
8934 SDValue VecIn =
Op.getOperand(0);
8942 IVecIn, IElt, Lane);
8951 EVT VecVT =
Op.getOperand(0).getValueType();
8954 assert(ST->hasMVEIntegerOps() &&
8955 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8958 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8959 unsigned Lane =
Op.getConstantOperandVal(1);
8960 unsigned LaneWidth =
8982 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8991 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8992 "Unexpected custom CONCAT_VECTORS lowering");
8994 "Unexpected custom CONCAT_VECTORS lowering");
8995 assert(ST->hasMVEIntegerOps() &&
8996 "CONCAT_VECTORS lowering only supported for MVE");
8999 EVT Op1VT =
V1.getValueType();
9000 EVT Op2VT = V2.getValueType();
9001 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9002 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9003 "Unexpected i1 concat operations!");
9016 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9021 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
9030 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9031 EVT NewVT = NewV.getValueType();
9032 EVT ConcatVT = ConVec.getValueType();
9033 unsigned ExtScale = 1;
9034 if (NewVT == MVT::v2f64) {
9035 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
9048 ConVec = ExtractInto(NewV1, ConVec, j);
9049 ConVec = ExtractInto(NewV2, ConVec, j);
9053 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
9059 while (ConcatOps.
size() > 1) {
9060 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
9063 ConcatOps[
I / 2] = ConcatPair(
V1, V2);
9067 return ConcatOps[0];
9072 EVT VT =
Op->getValueType(0);
9078 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9079 "unexpected CONCAT_VECTORS");
9100 EVT VT =
Op.getValueType();
9101 EVT Op1VT =
V1.getValueType();
9106 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9107 assert(ST->hasMVEIntegerOps() &&
9108 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9118 EVT SubVT = MVT::v4i32;
9120 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9130 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
9135 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9144 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9151 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9152 EVT VT =
N->getValueType(0);
9153 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9154 "Expected a vector i1 type!");
9156 EVT FromVT =
Op.getValueType();
9167 if (!Subtarget->hasMVEIntegerOps())
9170 EVT ToVT =
N->getValueType(0);
9213 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9215 EVT FromVT =
N->getOperand(0).getValueType();
9216 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9227 if (!Subtarget->hasMVEIntegerOps())
9232 EVT ToVT =
N->getValueType(0);
9233 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9236 EVT FromVT =
Op.getValueType();
9237 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9251 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9252 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9264 EVT VT =
N->getValueType(0);
9266 SDNode *BVN =
N->getOperand(0).getNode();
9271 unsigned HiElt = 1 - LoElt;
9276 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9292 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9293 SDNode *Elt =
N->getOperand(i).getNode();
9296 unsigned HalfSize = EltSize / 2;
9298 if (!
isIntN(HalfSize,
C->getSExtValue()))
9301 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9340 switch (OrigSimpleTy) {
9356 unsigned ExtOpcode) {
9379 if (ExtendedTy == LD->getMemoryVT())
9380 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9381 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9382 LD->getMemOperand()->getFlags());
9388 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9389 LD->getMemoryVT(), LD->getAlign(),
9390 LD->getMemOperand()->getFlags());
9403 N->getOperand(0)->getValueType(0),
9409 "Expected extending load");
9415 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9424 SDNode *BVN =
N->getOperand(0).getNode();
9426 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9434 EVT VT =
N->getValueType(0);
9440 for (
unsigned i = 0; i != NumElts; ++i) {
9441 const APInt &CInt =
N->getConstantOperandAPInt(i);
9450 unsigned Opcode =
N->getOpcode();
9452 SDNode *N0 =
N->getOperand(0).getNode();
9453 SDNode *N1 =
N->getOperand(1).getNode();
9461 unsigned Opcode =
N->getOpcode();
9463 SDNode *N0 =
N->getOperand(0).getNode();
9464 SDNode *N1 =
N->getOperand(1).getNode();
9474 EVT VT =
Op.getValueType();
9476 "unexpected type for custom-lowering ISD::MUL");
9477 SDNode *N0 =
Op.getOperand(0).getNode();
9478 SDNode *N1 =
Op.getOperand(1).getNode();
9479 unsigned NewOpc = 0;
9483 if (isN0SExt && isN1SExt)
9484 NewOpc = ARMISD::VMULLs;
9488 if (isN0ZExt && isN1ZExt)
9489 NewOpc = ARMISD::VMULLu;
9490 else if (isN1SExt || isN1ZExt) {
9494 NewOpc = ARMISD::VMULLs;
9497 NewOpc = ARMISD::VMULLu;
9501 NewOpc = ARMISD::VMULLu;
9507 if (VT == MVT::v2i64)
9524 "unexpected types for extended operands to VMULL");
9525 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9560 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9594 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9597 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9618 EVT VT =
Op.getValueType();
9619 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9620 "unexpected type for custom-lowering ISD::SDIV");
9627 if (VT == MVT::v8i8) {
9655 EVT VT =
Op.getValueType();
9656 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9657 "unexpected type for custom-lowering ISD::UDIV");
9664 if (VT == MVT::v8i8) {
9703 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9706 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9710 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9730 unsigned Opcode,
bool IsSigned) {
9731 EVT VT0 =
Op.getValue(0).getValueType();
9732 EVT VT1 =
Op.getValue(1).getValueType();
9734 bool InvertCarry = Opcode == ARMISD::SUBE;
9754 EVT VT =
Op.getValueType();
9755 assert((VT == MVT::i32 || VT == MVT::i64) &&
9756 "unexpected type for custom lowering DIV");
9762 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9764 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9771 for (
auto AI : {1, 0}) {
9772 SDValue Operand =
Op.getOperand(AI);
9773 Args.emplace_back(Operand,
9790ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9798 const bool MinSize =
ST.hasMinSize();
9799 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9800 :
ST.hasDivideInARMMode();
9804 if (
N->getOperand(0).getValueType().isVector())
9809 if (!(MinSize && HasDivide))
9816 return SDValue(
N, 0);
9822 if (Divisor.
sgt(128))
9825 return SDValue(
N, 0);
9830 assert(
Op.getValueType() == MVT::i32 &&
9831 "unexpected type for custom lowering DIV");
9834 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9837 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9843 if (
N->getValueType(0) == MVT::i32)
9844 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9847 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9851void ARMTargetLowering::ExpandDIV_Windows(
9856 assert(
Op.getValueType() == MVT::i64 &&
9857 "unexpected type for custom lowering DIV");
9862 SDValue
Result = LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9872std::pair<SDValue, SDValue>
9873ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9879 EVT MemVT =
LD->getMemoryVT();
9880 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9881 return std::make_pair(SDValue(), SDValue());
9884 unsigned AS =
LD->getAddressSpace();
9887 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9889 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9897 Opts, dl,
LD->getChain());
9904 SDValue EN = DAG.
getNode(ExtType, dl,
LD->getValueType(0), Pair.first);
9913 return std::make_pair(SDValue(), SDValue());
9922 EVT MemVT =
ST->getMemoryVT();
9923 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9927 unsigned AS =
ST->getAddressSpace();
9930 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9932 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9940 SDValue StoreVal =
ST->getOperand(1);
9941 if (
ST->isTruncatingStore())
9946 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9947 dl,
ST->getChain());
9949 return CallResult.second;
9960 EVT MemVT = LD->getMemoryVT();
9961 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9962 MemVT == MVT::v16i1) &&
9963 "Expected a predicate type!");
9964 assert(MemVT ==
Op.getValueType());
9966 "Expected a non-extending load");
9967 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9981 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9983 LD->getMemOperand());
9989 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9990 if (MemVT != MVT::v16i1)
9999 EVT MemVT =
LD->getMemoryVT();
10001 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10002 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
10003 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10004 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10007 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
10008 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10013 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
10014 auto Pair = LowerAEABIUnalignedLoad(SDValue(
N, 0), DAG);
10016 Results.push_back(Pair.first);
10017 Results.push_back(Pair.second);
10024 EVT MemVT = ST->getMemoryVT();
10025 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10026 MemVT == MVT::v16i1) &&
10027 "Expected a predicate type!");
10028 assert(MemVT == ST->getValue().getValueType());
10029 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10030 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10035 SDValue Build = ST->getValue();
10036 if (MemVT != MVT::v16i1) {
10049 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
10055 ST->getChain(), dl, GRP, ST->getBasePtr(),
10057 ST->getMemOperand());
10063 EVT MemVT =
ST->getMemoryVT();
10065 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10066 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
10067 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
10068 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10069 SDNode *
N =
Op.getNode();
10082 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10083 MemVT,
ST->getMemOperand());
10084 }
else if (Subtarget->hasMVEIntegerOps() &&
10085 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10086 MemVT == MVT::v16i1))) {
10088 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
10089 return LowerAEABIUnalignedStore(
Op, DAG);
10096 (
N->getOpcode() == ARMISD::VMOVIMM &&
10102 MVT VT =
Op.getSimpleValueType();
10104 SDValue PassThru =
N->getPassThru();
10115 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10116 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10117 N->getExtensionType(),
N->isExpandingLoad());
10120 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
10122 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10129 if (!ST->hasMVEIntegerOps())
10133 unsigned BaseOpcode = 0;
10134 switch (
Op->getOpcode()) {
10150 unsigned NumActiveLanes = NumElts;
10152 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10153 NumActiveLanes == 2) &&
10154 "Only expected a power 2 vector size");
10158 while (NumActiveLanes > 4) {
10159 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10161 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10162 NumActiveLanes /= 2;
10166 if (NumActiveLanes == 4) {
10176 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10177 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10178 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10184 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10188 if (EltVT !=
Op->getValueType(0))
10195 if (!ST->hasMVEFloatOps())
10202 if (!ST->hasNEON())
10210 unsigned PairwiseIntrinsic = 0;
10211 switch (
Op->getOpcode()) {
10215 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10218 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10221 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10224 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10230 unsigned NumActiveLanes = NumElts;
10232 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10233 NumActiveLanes == 2) &&
10234 "Only expected a power 2 vector size");
10240 VT =
Lo.getValueType();
10242 NumActiveLanes /= 2;
10246 while (NumActiveLanes > 1) {
10248 NumActiveLanes /= 2;
10255 if (EltVT !=
Op.getValueType()) {
10256 unsigned Extend = 0;
10257 switch (
Op->getOpcode()) {
10269 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10309 SDLoc dl(V0.getNode());
10314 const SDValue Ops[] = {RegClass, V0, SubReg0,
V1, SubReg1};
10320 SDLoc dl(V.getNode());
10321 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10331 assert(
N->getValueType(0) == MVT::i64 &&
10332 "AtomicCmpSwap on types less than 64 should be legal");
10341 ARM::CMP_SWAP_64,
SDLoc(
N),
10342 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10361 EVT VT =
Op.getValueType();
10362 SDValue Chain =
Op.getOperand(0);
10363 SDValue
LHS =
Op.getOperand(1);
10364 SDValue
RHS =
Op.getOperand(2);
10370 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10372 Chain, IsSignaling);
10373 if (!
RHS.getNode()) {
10387 SDValue ARMcc = DAG.
getConstant(CondCode, dl, MVT::i32);
10388 SDValue
Cmp = getVFPCmp(
LHS,
RHS, DAG, dl, IsSignaling);
10389 SDValue
Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10391 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10392 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10409 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10412 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10418 SDValue
LHS =
Op.getOperand(0);
10419 SDValue
RHS =
Op.getOperand(1);
10425 if (!IsSigned && Subtarget->isThumb1Only()) {
10434 SDValue Sub1WithFlags = DAG.
getNode(
10436 SDValue Sub1Result = Sub1WithFlags.
getValue(0);
10437 SDValue Flags1 = Sub1WithFlags.
getValue(1);
10443 Sub1Result, Sub1Result, Flags1);
10444 SDValue Sbc1Result = Sbc1.
getValue(0);
10453 SDValue Sbc2Result = Sbc2.
getValue(0);
10458 if (
Op.getValueType() != MVT::i32)
10472 unsigned Opcode = ARMISD::SUBC;
10476 SDValue SubLHS =
RHS.getOperand(0);
10477 SDValue SubRHS =
RHS.getOperand(1);
10481 bool CanUseAdd =
false;
10497 Opcode = ARMISD::ADDC;
10505 SDValue OpWithFlags =
10508 SDValue OpResult = OpWithFlags.
getValue(0);
10520 SDValue GTCondValue = DAG.
getConstant(GTCond, dl, MVT::i32);
10521 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10522 GTCondValue, Flags);
10525 SDValue LTCondValue = DAG.
getConstant(LTCond, dl, MVT::i32);
10526 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10527 LTCondValue, Flags);
10529 if (
Op.getValueType() != MVT::i32)
10537 switch (
Op.getOpcode()) {
10571 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10575 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10576 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10598 return LowerSET_FPMODE(
Op, DAG);
10600 return LowerRESET_FPMODE(
Op, DAG);
10604 !
Op.getValueType().isVector())
10605 return LowerDIV_Windows(
Op, DAG,
true);
10609 !
Op.getValueType().isVector())
10610 return LowerDIV_Windows(
Op, DAG,
false);
10626 return LowerALUO(
Op, DAG);
10634 EVT MemVT = LD->getMemoryVT();
10635 if (Subtarget->hasMVEIntegerOps() &&
10636 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10637 MemVT == MVT::v16i1))
10640 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10646 return LowerSTORE(
Op, DAG, Subtarget);
10671 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10680 return LowerSPONENTRY(
Op, DAG);
10682 return LowerFP_TO_BF16(
Op, DAG);
10683 case ARMISD::WIN__DBZCHK:
return SDValue();
10686 return LowerCMP(
Op, DAG);
10688 return LowerABS(
Op, DAG);
10693 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10694 Op.getOperand(1).getValueType() == MVT::bf16) &&
10695 "Expected custom lowering of rounding operations only for f16");
10698 {
Op.getOperand(0),
Op.getOperand(1)});
10699 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10700 {Ext.getValue(1), Ext.getValue(0)});
10707 unsigned IntNo =
N->getConstantOperandVal(0);
10709 if (IntNo == Intrinsic::arm_smlald)
10710 Opc = ARMISD::SMLALD;
10711 else if (IntNo == Intrinsic::arm_smlaldx)
10712 Opc = ARMISD::SMLALDX;
10713 else if (IntNo == Intrinsic::arm_smlsld)
10714 Opc = ARMISD::SMLSLD;
10715 else if (IntNo == Intrinsic::arm_smlsldx)
10716 Opc = ARMISD::SMLSLDX;
10722 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10726 N->getOperand(1),
N->getOperand(2),
10738 switch (
N->getOpcode()) {
10745 Res = ExpandBITCAST(
N, DAG, Subtarget);
10754 Res = LowerREM(
N, DAG);
10758 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10775 "can only expand DIV on Windows");
10787 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10816 "ROPI/RWPI not currently supported with SjLj");
10825 bool isThumb = Subtarget->isThumb();
10826 bool isThumb2 = Subtarget->
isThumb2();
10829 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10835 : &ARM::GPRRegClass;
10941 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10944 MachineRegisterInfo *MRI = &MF->
getRegInfo();
10949 : &ARM::GPRnopcRegClass;
10953 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10954 unsigned MaxCSNum = 0;
10955 for (MachineBasicBlock &BB : *MF) {
10961 for (MachineInstr &
II : BB) {
10962 if (!
II.isEHLabel())
10965 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10966 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10968 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10969 for (
unsigned Idx : CallSiteIdxs) {
10970 CallSiteNumToLPad[Idx].push_back(&BB);
10971 MaxCSNum = std::max(MaxCSNum, Idx);
10978 std::vector<MachineBasicBlock*> LPadList;
10979 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10980 LPadList.reserve(CallSiteNumToLPad.
size());
10981 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10982 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10983 for (MachineBasicBlock *
MBB : MBBList) {
10984 LPadList.push_back(
MBB);
10989 assert(!LPadList.empty() &&
10990 "No landing pad destinations for the dispatch jump table!");
10993 MachineJumpTableInfo *JTI =
11000 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
11003 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
11005 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
11008 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
11012 MF->insert(MF->end(), DispatchBB);
11013 MF->insert(MF->end(), DispContBB);
11014 MF->insert(MF->end(), TrapBB);
11018 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11020 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
11024 MachineInstrBuilder MIB;
11025 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11027 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
11037 unsigned NumLPads = LPadList.size();
11038 if (Subtarget->isThumb2()) {
11040 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11046 if (NumLPads < 256) {
11047 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11049 .
addImm(LPadList.size())
11053 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11054 .
addImm(NumLPads & 0xFFFF)
11057 unsigned VReg2 = VReg1;
11058 if ((NumLPads & 0xFFFF0000) != 0) {
11060 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11066 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11072 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11078 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11083 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11090 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11094 }
else if (Subtarget->isThumb()) {
11096 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11102 if (NumLPads < 256) {
11103 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11108 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11110 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11113 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11114 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11117 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11121 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11127 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11133 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11140 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11145 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11151 MachineMemOperand *JTMMOLd =
11156 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11162 unsigned NewVReg6 = NewVReg5;
11163 if (IsPositionIndependent) {
11165 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11172 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11177 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11183 if (NumLPads < 256) {
11184 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11188 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11190 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11191 .
addImm(NumLPads & 0xFFFF)
11194 unsigned VReg2 = VReg1;
11195 if ((NumLPads & 0xFFFF0000) != 0) {
11197 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11203 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11208 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11210 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11213 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11214 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11217 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11222 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11234 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11240 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11244 MachineMemOperand *JTMMOLd =
11248 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11255 if (IsPositionIndependent) {
11256 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11261 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11268 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11269 for (MachineBasicBlock *CurMBB : LPadList) {
11270 if (SeenMBBs.
insert(CurMBB).second)
11277 for (MachineBasicBlock *BB : InvokeBBs) {
11281 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11282 while (!Successors.empty()) {
11283 MachineBasicBlock *SMBB = Successors.pop_back_val();
11285 BB->removeSuccessor(SMBB);
11291 BB->normalizeSuccProbs();
11298 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11299 if (!
II->isCall())
continue;
11301 DenseSet<unsigned> DefRegs;
11303 OI =
II->operands_begin(), OE =
II->operands_end();
11305 if (!OI->isReg())
continue;
11306 DefRegs.
insert(OI->getReg());
11309 MachineInstrBuilder MIB(*MF, &*
II);
11311 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11312 unsigned Reg = SavedRegs[i];
11313 if (Subtarget->isThumb2() &&
11314 !ARM::tGPRRegClass.contains(
Reg) &&
11315 !ARM::hGPRRegClass.contains(
Reg))
11317 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11319 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11331 for (MachineBasicBlock *MBBLPad : MBBLPads)
11332 MBBLPad->setIsEHPad(
false);
11335 MI.eraseFromParent();
11348static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11350 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11351 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11353 return LdSize == 4 ? ARM::tLDRi
11354 : LdSize == 2 ? ARM::tLDRHi
11355 : LdSize == 1 ? ARM::tLDRBi : 0;
11357 return LdSize == 4 ? ARM::t2LDR_POST
11358 : LdSize == 2 ? ARM::t2LDRH_POST
11359 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11360 return LdSize == 4 ? ARM::LDR_POST_IMM
11361 : LdSize == 2 ? ARM::LDRH_POST
11362 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11367static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11369 return StSize == 16 ? ARM::VST1q32wb_fixed
11370 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11372 return StSize == 4 ? ARM::tSTRi
11373 : StSize == 2 ? ARM::tSTRHi
11374 : StSize == 1 ? ARM::tSTRBi : 0;
11376 return StSize == 4 ? ARM::t2STR_POST
11377 : StSize == 2 ? ARM::t2STRH_POST
11378 : StSize == 1 ? ARM::t2STRB_POST : 0;
11379 return StSize == 4 ? ARM::STR_POST_IMM
11380 : StSize == 2 ? ARM::STRH_POST
11381 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11388 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11389 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11390 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11391 assert(LdOpc != 0 &&
"Should have a load opcode");
11398 }
else if (IsThumb1) {
11404 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11409 }
else if (IsThumb2) {
11429 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11430 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11431 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11432 assert(StOpc != 0 &&
"Should have a store opcode");
11434 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11439 }
else if (IsThumb1) {
11446 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11451 }
else if (IsThumb2) {
11452 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11458 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11473 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11479 unsigned SizeVal =
MI.getOperand(2).getImm();
11484 MachineRegisterInfo &MRI = MF->
getRegInfo();
11485 unsigned UnitSize = 0;
11489 bool IsThumb1 = Subtarget->isThumb1Only();
11490 bool IsThumb2 = Subtarget->isThumb2();
11491 bool IsThumb = Subtarget->isThumb();
11493 if (Alignment & 1) {
11495 }
else if (Alignment & 2) {
11500 Subtarget->hasNEON()) {
11501 if ((Alignment % 16 == 0) && SizeVal >= 16)
11503 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11512 bool IsNeon = UnitSize >= 8;
11513 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11515 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11516 : UnitSize == 8 ? &ARM::DPRRegClass
11519 unsigned BytesLeft = SizeVal % UnitSize;
11520 unsigned LoopSize = SizeVal - BytesLeft;
11522 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11526 unsigned srcIn = src;
11527 unsigned destIn = dest;
11528 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11533 IsThumb1, IsThumb2);
11535 IsThumb1, IsThumb2);
11543 for (
unsigned i = 0; i < BytesLeft; i++) {
11548 IsThumb1, IsThumb2);
11550 IsThumb1, IsThumb2);
11554 MI.eraseFromParent();
11580 MF->
insert(It, loopMBB);
11581 MF->
insert(It, exitMBB);
11584 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11595 if (Subtarget->useMovt()) {
11596 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11599 }
else if (Subtarget->genExecuteOnly()) {
11600 assert(IsThumb &&
"Non-thumb expected to have used movt");
11605 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11609 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11610 MachineMemOperand *CPMMO =
11634 MachineBasicBlock *entryBB = BB;
11649 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11657 IsThumb1, IsThumb2);
11659 IsThumb1, IsThumb2);
11663 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11669 MachineInstrBuilder MIB =
11671 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11680 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11689 auto StartOfExit = exitMBB->
begin();
11693 unsigned srcIn = srcLoop;
11694 unsigned destIn = destLoop;
11695 for (
unsigned i = 0; i < BytesLeft; i++) {
11699 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11700 IsThumb1, IsThumb2);
11701 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11702 IsThumb1, IsThumb2);
11707 MI.eraseFromParent();
11715 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11718 assert(TM.getTargetTriple().isOSWindows() &&
11719 "__chkstk is only supported on Windows");
11720 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11740 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11741 if (ChkStkLibcall == RTLIB::Unsupported)
11745 switch (TM.getCodeModel()) {
11787 MI.eraseFromParent();
11796 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11811 .
addReg(
MI.getOperand(0).getReg())
11819 MI.eraseFromParent();
11843 if (miI == BB->
end()) {
11845 if (Succ->isLiveIn(ARM::CPSR))
11851 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11864 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11871 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11878 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11881 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11882 .
addUse(TotalIterationsReg)
11889 return TotalIterationsReg;
11900 Register TotalIterationsReg,
bool IsMemcpy) {
11909 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11919 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11927 Register RemainingLoopIterationsReg =
11929 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11930 .
addUse(TotalIterationsReg)
11932 .
addUse(RemainingLoopIterationsReg)
11938 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11939 .
addUse(ElementCountReg)
11941 .
addUse(RemainingElementsReg)
11946 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11947 .
addUse(PredCounterPhiReg)
11952 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11953 .
addUse(PredCounterPhiReg)
11962 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11971 SrcValueReg = OpSrcReg;
11973 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11984 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11985 .
addUse(LoopCounterPhiReg)
11988 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11989 .
addUse(RemainingLoopIterationsReg)
12007 "Invalid call instruction for a KCFI check");
12010 switch (
MBBI->getOpcode()) {
12013 case ARM::BLX_pred:
12014 case ARM::BLX_noip:
12015 case ARM::BLX_pred_noip:
12017 TargetOp = &
MBBI->getOperand(0);
12019 case ARM::TCRETURNri:
12020 case ARM::TCRETURNrinotr12:
12021 case ARM::TAILJMPr:
12022 case ARM::TAILJMPr4:
12023 TargetOp = &
MBBI->getOperand(0);
12029 case ARM::tBLXr_noip:
12030 case ARM::tBX_CALL:
12031 TargetOp = &
MBBI->getOperand(2);
12034 case ARM::tTAILJMPr:
12035 TargetOp = &
MBBI->getOperand(0);
12041 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
12045 unsigned KCFICheckOpcode;
12046 if (Subtarget->isThumb()) {
12047 if (Subtarget->isThumb2()) {
12048 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
12050 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
12053 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
12067 bool isThumb2 = Subtarget->isThumb2();
12068 switch (
MI.getOpcode()) {
12075 case ARM::tLDR_postidx: {
12079 .
add(
MI.getOperand(2))
12080 .
add(
MI.getOperand(3))
12081 .
add(
MI.getOperand(4))
12082 .
add(
MI.getOperand(0))
12084 MI.eraseFromParent();
12088 case ARM::MVE_MEMCPYLOOPINST:
12089 case ARM::MVE_MEMSETLOOPINST: {
12119 Register OpDestReg =
MI.getOperand(0).getReg();
12120 Register OpSrcReg =
MI.getOperand(1).getReg();
12121 Register OpSizeReg =
MI.getOperand(2).getReg();
12141 if (TpExit == BB) {
12143 "block containing memcpy/memset Pseudo");
12153 genTPEntry(TpEntry, TpLoopBody, TpExit, OpSizeReg,
TII, dl, MRI);
12156 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12158 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12161 Properties.resetNoPHIs();
12173 MI.eraseFromParent();
12183 case ARM::t2STR_preidx:
12184 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12186 case ARM::t2STRB_preidx:
12187 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12189 case ARM::t2STRH_preidx:
12190 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12193 case ARM::STRi_preidx:
12194 case ARM::STRBi_preidx: {
12195 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12196 : ARM::STRB_PRE_IMM;
12198 unsigned Offset =
MI.getOperand(4).getImm();
12206 .
add(
MI.getOperand(0))
12207 .
add(
MI.getOperand(1))
12208 .
add(
MI.getOperand(2))
12210 .
add(
MI.getOperand(5))
12211 .
add(
MI.getOperand(6))
12213 MI.eraseFromParent();
12216 case ARM::STRr_preidx:
12217 case ARM::STRBr_preidx:
12218 case ARM::STRH_preidx: {
12220 switch (
MI.getOpcode()) {
12222 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12223 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12224 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12229 MI.eraseFromParent();
12233 case ARM::tMOVCCr_pseudo: {
12251 F->insert(It, copy0MBB);
12252 F->insert(It, sinkMBB);
12255 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12261 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12277 .
addImm(
MI.getOperand(3).getImm())
12278 .
addReg(
MI.getOperand(4).getReg());
12293 .
addReg(
MI.getOperand(1).getReg())
12295 .
addReg(
MI.getOperand(2).getReg())
12298 MI.eraseFromParent();
12303 case ARM::BCCZi64: {
12309 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12314 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12318 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12324 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12328 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12338 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12347 MI.eraseFromParent();
12351 case ARM::Int_eh_sjlj_setjmp:
12352 case ARM::Int_eh_sjlj_setjmp_nofp:
12353 case ARM::tInt_eh_sjlj_setjmp:
12354 case ARM::t2Int_eh_sjlj_setjmp:
12355 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12358 case ARM::Int_eh_sjlj_setup_dispatch:
12359 EmitSjLjDispatchBlock(
MI, BB);
12361 case ARM::COPY_STRUCT_BYVAL_I32:
12363 return EmitStructByval(
MI, BB);
12364 case ARM::WIN__CHKSTK:
12365 return EmitLowered__chkstk(
MI, BB);
12366 case ARM::WIN__DBZCHK:
12367 return EmitLowered__dbzchk(
MI, BB);
12383 if (!
Node->hasAnyUseOfValue(0)) {
12384 MI.getOperand(0).setIsDead(
true);
12386 if (!
Node->hasAnyUseOfValue(1)) {
12387 MI.getOperand(1).setIsDead(
true);
12391 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12393 : &ARM::GPRRegClass);
12400 if (
MI.getOpcode() == ARM::MEMCPY) {
12421 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12422 &&
"converted opcode should be the same except for cc_out"
12423 " (and, on Thumb1, pred)");
12431 if (Subtarget->isThumb1Only()) {
12432 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12433 MI.addOperand(
MI.getOperand(1));
12434 MI.removeOperand(1);
12438 for (
unsigned i =
MI.getNumOperands(); i--;) {
12440 if (
op.isReg() &&
op.isUse()) {
12443 MI.tieOperands(DefIdx, i);
12451 ccOutIdx =
MCID->getNumOperands() - 1;
12453 ccOutIdx =
MCID->getNumOperands() - 1;
12457 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12458 assert(!NewOpc &&
"Optional cc_out operand required");
12463 bool definesCPSR =
false;
12464 bool deadCPSR =
false;
12465 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12469 definesCPSR =
true;
12472 MI.removeOperand(i);
12476 if (!definesCPSR) {
12477 assert(!NewOpc &&
"Optional cc_out operand required");
12480 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12482 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12483 "expect uninitialized optional cc_out operand");
12485 if (!Subtarget->isThumb1Only())
12521 switch (
N->getOpcode()) {
12522 default:
return false;
12524 CC =
N->getOperand(0);
12546 EVT VT =
N->getValueType(0);
12547 CC =
N->getOperand(0);
12594 EVT VT =
N->getValueType(0);
12597 bool SwapSelectOps;
12599 NonConstantVal, DAG))
12605 OtherOp, NonConstantVal);
12611 CCOp, TrueVal, FalseVal);
12631 if (
N->getOpcode() == ARMISD::VUZP)
12635 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12650 if (!
N->getValueType(0).is64BitVector())
12658 EVT VT =
N->getValueType(0);
12697 EVT VT =
N->getValueType(0);
12703 Opcode = Intrinsic::arm_neon_vpaddls;
12705 Opcode = Intrinsic::arm_neon_vpaddlu;
12733 EVT VT =
N->getValueType(0);
12748 unsigned nextIndex = 0;
12799 Ops.push_back(Vec);
12816 return DAG.
getNode(ExtOp, dl, VT, tmp);
12847 if (SRA.getOpcode() !=
ISD::SRA) {
12854 if (Const->getZExtValue() != 31)
12859 if (SRA.getOperand(0) !=
Mul)
12863 SDLoc dl(AddcNode);
12864 unsigned Opcode = 0;
12869 Opcode = ARMISD::SMLALBB;
12870 Op0 =
Mul.getOperand(0);
12871 Op1 =
Mul.getOperand(1);
12873 Opcode = ARMISD::SMLALBT;
12874 Op0 =
Mul.getOperand(0);
12875 Op1 =
Mul.getOperand(1).getOperand(0);
12877 Opcode = ARMISD::SMLALTB;
12878 Op0 =
Mul.getOperand(0).getOperand(0);
12879 Op1 =
Mul.getOperand(1);
12881 Opcode = ARMISD::SMLALTT;
12882 Op0 =
Mul->getOperand(0).getOperand(0);
12883 Op1 =
Mul->getOperand(1).getOperand(0);
12899 SDValue resNode(AddcNode, 0);
12927 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12928 "Expect an ADDE or SUBE");
12932 "ADDE node has the wrong inputs");
12936 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12937 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12938 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12939 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12951 "Expect ADDC with two result values. First: i32");
12955 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12971 bool IsLeftOperandMUL =
false;
12976 IsLeftOperandMUL =
true;
12987 SDValue *LowAddSub =
nullptr;
12990 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12993 if (IsLeftOperandMUL)
12994 HiAddSub = &AddeSubeOp1;
12996 HiAddSub = &AddeSubeOp0;
13001 if (AddcSubcOp0 == MULOp.
getValue(0)) {
13002 LoMul = &AddcSubcOp0;
13003 LowAddSub = &AddcSubcOp1;
13005 if (AddcSubcOp1 == MULOp.
getValue(0)) {
13006 LoMul = &AddcSubcOp1;
13007 LowAddSub = &AddcSubcOp0;
13015 if (AddcSubcNode == HiAddSub->getNode() ||
13031 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13036 Ops.push_back(*HiAddSub);
13037 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
13038 FinalOpc = ARMISD::SMMLSR;
13040 FinalOpc = ARMISD::SMMLAR;
13045 return SDValue(AddeSubeNode, 0);
13046 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
13052 Ops.push_back(*LowAddSub);
13053 Ops.push_back(*HiAddSub);
13066 return SDValue(AddeSubeNode, 0);
13078 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13083 if (AddcNode->
getOpcode() != ARMISD::ADDC)
13087 SDNode *UmlalNode =
nullptr;
13126 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13131 SDNode* AddcNode =
N->getOperand(2).getNode();
13132 SDNode* AddeNode =
N->getOperand(3).getNode();
13133 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
13134 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
13140 {N->getOperand(0), N->getOperand(1),
13141 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13151 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13155 if (
LHS->getOpcode() == ARMISD::ADDE &&
13165 int32_t imm =
C->getSExtValue();
13166 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13169 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13171 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13186 int64_t imm =
C->getSExtValue();
13195 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13197 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13198 N->getOperand(0),
RHS,
N->getOperand(2));
13210 if (!Subtarget->hasMVEIntegerOps())
13223 SetCC =
N->getOperand(0);
13227 TrueVal =
N->getOperand(1);
13228 FalseVal =
N->getOperand(2);
13230 LHS =
N->getOperand(0);
13231 RHS =
N->getOperand(1);
13233 TrueVal =
N->getOperand(2);
13234 FalseVal =
N->getOperand(3);
13239 unsigned int Opcode = 0;
13243 Opcode = ARMISD::VMINVu;
13249 Opcode = ARMISD::VMINVs;
13255 Opcode = ARMISD::VMAXVu;
13261 Opcode = ARMISD::VMAXVs;
13268 switch (TrueVal->getOpcode()) {
13287 if (TrueVal !=
LHS || FalseVal !=
RHS)
13290 EVT LeftType =
LHS->getValueType(0);
13291 EVT RightType =
RHS->getValueType(0);
13294 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13298 if (VectorScalarType != MVT::i32)
13306 if (VectorScalarType != MVT::i32)
13319 EVT VT =
N->getValueType(0);
13327 Shft =
N->getOperand(0);
13334 Cmp.getOperand(0) !=
N->getOperand(1) ||
13335 Cmp.getOperand(1) !=
N->getOperand(2))
13337 Shft =
N->getOperand(1);
13349 ScalarType = MVT::i8;
13352 case (1 << 15) - 1:
13353 ScalarType = MVT::i16;
13356 case (1ULL << 31) - 1:
13357 ScalarType = MVT::i32;
13388 unsigned LegalLanes = 128 / (ShftAmt + 1);
13400 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13401 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13402 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13403 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13412 for (
unsigned I = 0;
I < NumParts; ++
I) {
13419 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13429 if (!Subtarget->hasMVEIntegerOps())
13434 if (
N->getOperand(0).getOpcode() == ARMISD::PREDICATE_CAST &&
13436 unsigned C =
N->getOperand(0).getConstantOperandVal(0);
13438 return N->getOperand(2);
13440 return N->getOperand(1);
13455 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13465 if (!Const || !Const->isOne())
13483 EVT VT =
N->getValueType(0);
13485 if (!Subtarget->hasMVEIntegerOps() ||
13514 Opc = Intrinsic::arm_mve_vctp64;
13517 Opc = Intrinsic::arm_mve_vctp32;
13520 Opc = Intrinsic::arm_mve_vctp16;
13523 Opc = Intrinsic::arm_mve_vctp8;
13577 EVT VT =
N->getValueType(0);
13583 switch (
Op.getOpcode()) {
13585 case ARMISD::VADDVs:
13586 case ARMISD::VADDVu:
13587 case ARMISD::VMLAVs:
13588 case ARMISD::VMLAVu:
13608 unsigned N0RedOp = 0;
13615 unsigned N1RedOp = 0;
13629 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13631 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13638 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13662 if (!BaseLocDecomp0.getBase() ||
13663 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13664 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13666 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13668 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13678 if (IsBefore < 0) {
13681 }
else if (IsBefore > 0) {
13694 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13704 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13714 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13716 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13723 if (!Subtarget->hasMVEIntegerOps())
13729 EVT VT =
N->getValueType(0);
13734 if (VT != MVT::i64)
13745 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13765 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13774 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13776 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13778 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13780 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13782 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13784 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13786 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13788 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13790 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13792 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13794 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13796 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13798 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13800 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13802 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13804 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13814 "Expected shift op");
13816 SDValue ShiftLHS =
N->getOperand(0);
13830 if (Subtarget->isThumb1Only()) {
13841 if (Const->getAPIntValue().ult(256))
13844 Const->getAPIntValue().sgt(-256))
13860 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13861 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13862 "Expected XOR(SHIFT) pattern");
13867 if (XorC && ShiftC) {
13868 unsigned MaskIdx, MaskLen;
13869 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13870 unsigned ShiftAmt = ShiftC->getZExtValue();
13871 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13872 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13873 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13874 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13884 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13886 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13887 "Expected shift-shift mask");
13889 if (!Subtarget->isThumb1Only())
13892 EVT VT =
N->getValueType(0);
13900 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13902 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13907 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps()) {
13908 if (Subtarget->isThumb1Only())
13922 return Subtarget->hasVFP2Base();
13924 return Subtarget->hasVFP2Base();
13926 return Subtarget->hasFP64();
13929 return Subtarget->hasMVEFloatOps();
13958 if (ST->isThumb1Only())
13962 for (
auto *U :
N->users()) {
13963 switch(U->getOpcode()) {
13981 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13982 U->getOperand(1).getOpcode() ==
ISD::SHL)
13992 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13999 if (!C1ShlC2 || !C2)
14002 APInt C2Int = C2->getAPIntValue();
14003 APInt C1Int = C1ShlC2->getAPIntValue();
14005 if (C2Int.
uge(C2Width))
14011 if ((C1Int & Mask) != C1Int)
14018 auto LargeImm = [](
const APInt &
Imm) {
14019 unsigned Zeros =
Imm.countl_zero() +
Imm.countr_zero();
14020 return Imm.getBitWidth() - Zeros > 8;
14023 if (LargeImm(C1Int) || LargeImm(C2Int))
14035 SHL.dump();
N->dump());
14096 if (
Op.hasOneUse() && ShiftAmt &&
14097 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
14155 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14176 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14197 if (!Subtarget->hasVMLxForwarding())
14216 EVT VT =
N->getValueType(0);
14227 EVT VT =
N->getValueType(0);
14228 if (VT != MVT::v2i64)
14239 return Op->getOperand(0);
14253 And =
And->getOperand(0);
14258 Mask = Mask->getOperand(0);
14261 Mask.getValueType() != MVT::v4i32)
14267 return And->getOperand(0);
14272 if (
SDValue Op0 = IsSignExt(N0)) {
14273 if (
SDValue Op1 = IsSignExt(N1)) {
14274 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14275 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14276 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14279 if (
SDValue Op0 = IsZeroExt(N0)) {
14280 if (
SDValue Op1 = IsZeroExt(N1)) {
14281 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14282 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14283 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14295 EVT VT =
N->getValueType(0);
14296 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14307 if (VT != MVT::i32)
14314 int64_t MulAmt =
C->getSExtValue();
14317 ShiftAmt = ShiftAmt & (32 - 1);
14322 MulAmt >>= ShiftAmt;
14383 if (
N->getValueType(0) != MVT::i32)
14392 if (C1 == 255 || C1 == 65535)
14395 SDNode *N0 =
N->getOperand(0).getNode();
14409 if (!C2 || C2 >= 32)
14453 if (Trailing == C2 && C2 + C3 < 32) {
14466 if (Leading == C2 && C2 + C3 < 32) {
14494 EVT VT =
N->getValueType(0);
14498 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14501 APInt SplatBits, SplatUndef;
14502 unsigned SplatBitSize;
14504 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14505 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14506 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14507 SplatBitSize == 64) {
14514 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14516 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14541 if (!Subtarget->hasV6Ops() ||
14542 (Subtarget->isThumb() &&
14543 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14546 SDValue SRL = OR->getOperand(0);
14547 SDValue SHL = OR->getOperand(1);
14550 SRL = OR->getOperand(1);
14551 SHL = OR->getOperand(0);
14558 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14562 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14563 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14564 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14583 unsigned Opcode = 0;
14584 if (
isS16(OpS16, DAG))
14585 Opcode = ARMISD::SMULWB;
14587 Opcode = ARMISD::SMULWT;
14602 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14605 EVT VT =
N->getValueType(0);
14620 if (VT != MVT::i32)
14633 if (Mask == 0xffff)
14640 if ((Val & ~Mask) != Val)
14646 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14665 (Mask == ~Mask2)) {
14668 if (Subtarget->hasDSP() &&
14669 (Mask == 0xffff || Mask == 0xffff0000))
14675 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14682 (~Mask == Mask2)) {
14685 if (Subtarget->hasDSP() &&
14686 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14742 if (
N->getOpcode() == ARMISD::VCMP)
14744 else if (
N->getOpcode() == ARMISD::VCMPZ)
14752 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14759 EVT VT =
N->getValueType(0);
14764 auto IsFreelyInvertable = [&](
SDValue V) {
14765 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14771 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14789 if (AndOp.getOpcode() !=
ISD::AND)
14793 SDValue Mask = AndOp.getOperand(1);
14803 bool IsShiftRight =
false;
14806 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14807 IsShiftRight =
true;
14810 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14818 APInt RequiredMask = IsShiftRight
14821 if (MaskBits != RequiredMask)
14824 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14834 EVT VT =
N->getValueType(0);
14840 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14841 VT == MVT::v8i1 || VT == MVT::v16i1))
14844 APInt SplatBits, SplatUndef;
14845 unsigned SplatBitSize;
14847 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14848 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14849 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14850 SplatBitSize == 64) {
14857 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14859 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14879 (Subtarget->hasMVEIntegerOps() &&
14880 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14883 return ShiftInsert;
14887 return ShiftInsert;
14901 unsigned SplatBitSize;
14904 APInt SplatBits0, SplatBits1;
14908 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14909 HasAnyUndefs) && !HasAnyUndefs) {
14910 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14911 HasAnyUndefs) && !HasAnyUndefs) {
14916 SplatBits0 == ~SplatBits1) {
14924 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14944 if (CSINC.
getOpcode() != ARMISD::CSINC)
14946 if (CSINC.
getOpcode() == ARMISD::CSINC &&
14959 EVT VT =
N->getValueType(0);
14974 if (Subtarget->hasMVEIntegerOps()) {
15002 assert(
N->getOpcode() == ARMISD::BFI);
15005 ToMask =
~N->getConstantOperandAPInt(2);
15025 unsigned LastActiveBitInA =
A.countr_zero();
15026 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
15027 return LastActiveBitInA - 1 == FirstActiveBitInB;
15032 APInt ToMask, FromMask;
15037 if (V.getOpcode() != ARMISD::BFI)
15040 APInt NewToMask, NewFromMask;
15042 if (NewFrom != From)
15046 if ((NewToMask & ToMask).getBoolValue())
15071 unsigned InvMask =
N->getConstantOperandVal(2);
15075 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
15076 "undefined behavior");
15077 unsigned Mask = (1u << Width) - 1;
15079 if ((Mask & (~Mask2)) == 0)
15081 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
15088 APInt ToMask1, FromMask1;
15091 APInt ToMask2, FromMask2;
15097 APInt NewFromMask = FromMask1 | FromMask2;
15098 APInt NewToMask = ToMask1 | ToMask2;
15100 EVT VT =
N->getValueType(0);
15103 if (NewFromMask[0] == 0)
15106 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
15114 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
15115 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
15116 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
15118 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
15122 EVT VT =
N->getValueType(0);
15125 N->getOperand(1),
N->getOperand(2));
15137 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
15139 SDValue CSInc = Cmp->getOperand(0);
15149 if (CSInc.
getOpcode() == ARMISD::CSINC &&
15189 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15190 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15193 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15195 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15208 SDValue InDouble =
N->getOperand(0);
15209 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15223 SDValue BasePtr = LD->getBasePtr();
15225 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15226 LD->getAlign(), LD->getMemOperand()->getFlags());
15232 LD->getPointerInfo().getWithOffset(4),
15234 LD->getMemOperand()->getFlags());
15253 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15267 if (!Subtarget->
isLittle() && BVSwap)
15285 if (!Subtarget->
isLittle() && BVSwap)
15304 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15317 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15330 if (Copy.getValueType() == MVT::f32 &&
15332 bool HasGlue = Copy->getNumOperands() == 3;
15333 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15334 HasGlue ? Copy->getOperand(2) :
SDValue()};
15335 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15354 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15355 LN0->getMemoryVT() == MVT::i16) {
15358 LN0->getBasePtr(), LN0->getMemOperand());
15376 EVT VT =
N->getValueType(0);
15410 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15411 for (
unsigned i = 0; i < NumElts; ++i) {
15412 SDNode *Elt =
N->getOperand(i).getNode();
15429 if (
N->getNumOperands() == 2)
15435 EVT VT =
N->getValueType(0);
15441 for (
unsigned i = 0; i < NumElts; ++i) {
15467 EVT VT =
N->getValueType(0);
15475 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15480 Use->getValueType(0).isFloatingPoint())
15488 unsigned NumOfBitCastedElts = 0;
15490 unsigned NumOfRelevantElts = NumElts;
15491 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15496 ++NumOfBitCastedElts;
15500 --NumOfRelevantElts;
15504 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15522 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15527 V->getOperand(0).getValueType() == MVT::i32)
15529 V = V.getOperand(0);
15546 EVT VT =
N->getValueType(0);
15551 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15553 if (
Op->getOperand(0).getValueType() == VT)
15554 return Op->getOperand(0);
15555 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15562 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15569 if (
Op.getValueType() == MVT::i32) {
15580 EVT VT =
N->getValueType(0);
15585 if (ST->isLittle())
15589 if (
Op.getValueType() == VT)
15596 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15598 if (
Op->getOperand(0).getValueType() == VT)
15599 return Op->getOperand(0);
15600 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15608 if (!Subtarget->hasMVEIntegerOps())
15611 EVT VT =
N->getValueType(0);
15619 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15625 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15629 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15642 EVT VT =
N->getValueType(0);
15643 SDNode *Elt =
N->getOperand(1).getNode();
15658 Vec, V,
N->getOperand(2));
15668 EVT VT =
N->getValueType(0);
15696 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15697 isa<ConstantSDNode>(V->getOperand(1)) &&
15698 V->getConstantOperandVal(1) == Lane + 1 &&
15699 V->getOperand(0).getResNo() == ResNo;
15701 if (OtherIt == Op0->
users().
end())
15706 SDValue OtherExt(*OtherIt, 0);
15718 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15721 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15731 EVT VT =
N->getValueType(0);
15735 if (Op0->
getOpcode() == ARMISD::VDUP) {
15737 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15738 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15739 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15740 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15741 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15744 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15745 X =
X->getOperand(0);
15746 if (
X.getValueType() == VT)
15754 return Op0.
getOperand(
N->getConstantOperandVal(1));
15764 unsigned Offset =
N->getConstantOperandVal(1);
15766 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15776 unsigned Idx =
N->getConstantOperandVal(1);
15791 unsigned Lane =
N->getConstantOperandVal(1);
15819 EVT VT =
N->getValueType(0);
15822 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15824 Op.getOperand(0).getValueType().getScalarType())
15825 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15834 SDValue SubVec =
N->getOperand(1);
15835 uint64_t IdxVal =
N->getConstantOperandVal(2);
15846 if (IdxVal == 0 && Vec.
isUndef())
15852 (IdxVal != 0 && IdxVal != NumSubElts))
15883 ARMISD::VMOVN,
DL, VT,
15889 ARMISD::VMOVN,
DL, VT,
15925 EVT VT =
N->getValueType(0);
15936 unsigned HalfElts = NumElts/2;
15938 for (
unsigned n = 0; n < NumElts; ++n) {
15941 if (MaskElt < (
int)HalfElts)
15943 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15944 NewElt = HalfElts + MaskElt - NumElts;
15987 bool SimpleConstIncOnly,
15995 bool isLoadOp =
true;
15996 bool isLaneOp =
false;
15999 bool hasAlignment =
true;
16000 unsigned NewOpc = 0;
16001 unsigned NumVecs = 0;
16002 if (
Target.isIntrinsic) {
16003 unsigned IntNo =
N->getConstantOperandVal(1);
16007 case Intrinsic::arm_neon_vld1:
16011 case Intrinsic::arm_neon_vld2:
16015 case Intrinsic::arm_neon_vld3:
16019 case Intrinsic::arm_neon_vld4:
16023 case Intrinsic::arm_neon_vld1x2:
16026 hasAlignment =
false;
16028 case Intrinsic::arm_neon_vld1x3:
16031 hasAlignment =
false;
16033 case Intrinsic::arm_neon_vld1x4:
16036 hasAlignment =
false;
16038 case Intrinsic::arm_neon_vld2dup:
16042 case Intrinsic::arm_neon_vld3dup:
16046 case Intrinsic::arm_neon_vld4dup:
16050 case Intrinsic::arm_neon_vld2lane:
16055 case Intrinsic::arm_neon_vld3lane:
16060 case Intrinsic::arm_neon_vld4lane:
16065 case Intrinsic::arm_neon_vst1:
16070 case Intrinsic::arm_neon_vst2:
16071 NewOpc = ARMISD::VST2_UPD;
16075 case Intrinsic::arm_neon_vst3:
16080 case Intrinsic::arm_neon_vst4:
16081 NewOpc = ARMISD::VST4_UPD;
16085 case Intrinsic::arm_neon_vst2lane:
16091 case Intrinsic::arm_neon_vst3lane:
16097 case Intrinsic::arm_neon_vst4lane:
16103 case Intrinsic::arm_neon_vst1x2:
16107 hasAlignment =
false;
16109 case Intrinsic::arm_neon_vst1x3:
16113 hasAlignment =
false;
16115 case Intrinsic::arm_neon_vst1x4:
16119 hasAlignment =
false;
16124 switch (
N->getOpcode()) {
16160 VecTy =
N->getValueType(0);
16161 }
else if (
Target.isIntrinsic) {
16162 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16165 "Node has to be a load, a store, or an intrinsic!");
16166 VecTy =
N->getOperand(1).getValueType();
16174 if (isLaneOp || isVLDDUPOp)
16177 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16183 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16192 EVT AlignedVecTy = VecTy;
16212 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16213 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16224 Alignment =
Align(1);
16230 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16232 for (n = 0; n < NumResultVecs; ++n)
16233 Tys[n] = AlignedVecTy;
16234 Tys[n++] = MVT::i32;
16235 Tys[n] = MVT::Other;
16240 Ops.push_back(
N->getOperand(0));
16241 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16246 Ops.push_back(StN->getValue());
16250 unsigned LastOperand =
16251 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16252 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16253 Ops.push_back(
N->getOperand(i));
16257 Ops.push_back(DAG.
getConstant(Alignment.value(), dl, MVT::i32));
16261 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16272 for (
unsigned i = 0; i < NumResultVecs; ++i)
16277 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16278 SDValue &LdVal = NewResults[0];
16314 switch (
N->getOpcode()) {
16318 *Ptr =
N->getOperand(0);
16319 *CInc =
N->getOperand(1);
16326 *Ptr =
N->getOperand(1);
16327 *CInc =
N->getOperand(2);
16354 SDValue Addr =
N->getOperand(AddrOpIdx);
16365 unsigned ConstInc =
16370 if (BaseUpdates.
size() >= MaxBaseUpdates)
16391 unsigned UserOffset =
16394 if (!UserOffset || UserOffset <=
Offset)
16397 unsigned NewConstInc = UserOffset -
Offset;
16400 if (BaseUpdates.
size() >= MaxBaseUpdates)
16408 unsigned NumValidUpd = BaseUpdates.
size();
16409 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16420 return LHS.ConstInc <
RHS.ConstInc;
16449 unsigned IntNo =
N->getConstantOperandVal(1);
16450 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16452 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16475 bool isLoadOp =
true;
16476 unsigned NewOpc = 0;
16477 unsigned NumVecs = 0;
16481 case Intrinsic::arm_mve_vld2q:
16485 case Intrinsic::arm_mve_vld4q:
16489 case Intrinsic::arm_mve_vst2q:
16490 NewOpc = ARMISD::VST2_UPD;
16494 case Intrinsic::arm_mve_vst4q:
16495 NewOpc = ARMISD::VST4_UPD;
16504 VecTy =
N->getValueType(0);
16506 VecTy =
N->getOperand(3).getValueType();
16520 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16522 for (n = 0; n < NumResultVecs; ++n)
16524 Tys[n++] = MVT::i32;
16525 Tys[n] = MVT::Other;
16530 Ops.push_back(
N->getOperand(0));
16531 Ops.push_back(
N->getOperand(2));
16532 Ops.push_back(Inc);
16534 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16535 Ops.push_back(
N->getOperand(i));
16542 for (
unsigned i = 0; i < NumResultVecs; ++i)
16561 EVT VT =
N->getValueType(0);
16567 SDNode *VLD =
N->getOperand(0).getNode();
16570 unsigned NumVecs = 0;
16571 unsigned NewOpc = 0;
16573 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16576 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16579 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16591 if (
Use.getResNo() == NumVecs)
16594 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16595 VLDLaneNo !=
User->getConstantOperandVal(1))
16602 for (n = 0; n < NumVecs; ++n)
16604 Tys[n] = MVT::Other;
16614 unsigned ResNo =
Use.getResNo();
16616 if (ResNo == NumVecs)
16623 std::vector<SDValue> VLDDupResults;
16624 for (
unsigned n = 0; n < NumVecs; ++n)
16638 EVT VT =
N->getValueType(0);
16641 if (Subtarget->hasMVEIntegerOps()) {
16645 ExtractVT = MVT::i32;
16647 N->getOperand(0),
N->getOperand(1));
16659 Op =
Op.getOperand(0);
16660 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16664 unsigned EltSize =
Op.getScalarValueSizeInBits();
16666 unsigned Imm =
Op.getConstantOperandVal(0);
16682 if (Subtarget->hasMVEIntegerOps()) {
16685 if (
Op.getValueType() == MVT::f32)
16686 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16688 else if (
Op.getValueType() == MVT::f16)
16689 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16690 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16693 if (!Subtarget->hasNEON())
16700 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16701 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16702 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16707 LD->getMemoryVT(), LD->getMemOperand());
16718 EVT VT =
N->getValueType(0);
16733 SDValue StVal = St->getValue();
16735 if (!St->isTruncatingStore() || !VT.
isVector())
16738 EVT StVT = St->getMemoryVT();
16740 assert(StVT != VT &&
"Cannot truncate to the same type");
16750 if (0 != (NumElems * FromEltSz) % ToEltSz)
16753 unsigned SizeRatio = FromEltSz / ToEltSz;
16758 NumElems * SizeRatio);
16764 for (
unsigned i = 0; i < NumElems; ++i)
16778 MVT StoreType = MVT::i8;
16780 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16796 SDValue BasePtr = St->getBasePtr();
16800 for (
unsigned I = 0;
I <
E;
I++) {
16804 DAG.
getStore(St->getChain(),
DL, SubVec, BasePtr, St->getPointerInfo(),
16805 St->getAlign(), St->getMemOperand()->getFlags());
16818 if (!St->isSimple() || St->isTruncatingStore() || !St->isUnindexed())
16820 SDValue Trunc = St->getValue();
16831 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16834 unsigned NumElements = 4;
16851 unsigned Off0 = Rev ? NumElts : 0;
16852 unsigned Off1 = Rev ? 0 : NumElts;
16854 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16855 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16857 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16865 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16872 SDValue BasePtr = St->getBasePtr();
16873 Align Alignment = St->getBaseAlign();
16885 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16896 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16899 Ch,
DL, Extract, NewPtr, St->getPointerInfo().getWithOffset(NewOffset),
16900 NewToVT, Alignment, MMOFlags, AAInfo);
16911 if (!St->isSimple() || St->isTruncatingStore() || !St->isUnindexed())
16913 SDValue Trunc = St->getValue();
16923 SDValue BasePtr = St->getBasePtr();
16924 Align Alignment = St->getBaseAlign();
16933 unsigned NewOffset =
16940 Ch,
DL, Extract, NewPtr, St->getPointerInfo().getWithOffset(NewOffset),
16941 NewToVT, Alignment, MMOFlags, AAInfo);
16952 if (!St->isSimple() || St->isTruncatingStore() || !St->isUnindexed())
16954 SDValue Extract = St->getValue();
16963 {Extract.getOperand(0), Extract.getOperand(1)});
16971 SDValue BasePtr = St->getBasePtr();
16972 Align Alignment = St->getBaseAlign();
16977 St->getPointerInfo(), NewToVT, Alignment,
16989 if (St->isVolatile())
16991 SDValue StVal = St->getValue();
16994 if (Subtarget->hasNEON())
16998 if (Subtarget->hasMVEFloatOps())
17002 if (Subtarget->hasMVEIntegerOps()) {
17019 SDValue BasePtr = St->getBasePtr();
17022 BasePtr, St->getPointerInfo(), St->getBaseAlign(),
17023 St->getMemOperand()->getFlags());
17029 St->getPointerInfo().getWithOffset(4),
17030 St->getBaseAlign(), St->getMemOperand()->
getFlags());
17052 return DAG.
getStore(St->getChain(), dl, V, St->getBasePtr(),
17053 St->getPointerInfo(), St->getAlign(),
17054 St->getMemOperand()->getFlags(), St->getAAInfo());
17076 if (!Subtarget->hasNEON())
17080 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
17088 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
17090 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
17091 uint32_t IntBits = IntTy.getSizeInBits();
17092 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17093 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17104 if (
C == -1 ||
C == 0 ||
C > 32)
17109 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
17110 Intrinsic::arm_neon_vcvtfp2fxu;
17113 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
17116 if (IntBits < FloatBits)
17124 if (!Subtarget->hasMVEFloatOps())
17132 EVT VT =
N->getValueType(0);
17137 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
17139 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
17141 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
17142 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
17144 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17157 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17168 EVT VT =
N->getValueType(0);
17171 if (!
N->getFlags().hasAllowReassociation())
17178 unsigned Opc =
A.getConstantOperandVal(0);
17179 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17184 A.getOperand(3),
A.getOperand(4));
17216 if (!Subtarget->hasNEON())
17220 unsigned OpOpcode =
Op.getNode()->getOpcode();
17221 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17225 SDValue ConstVec =
N->getOperand(1);
17229 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17231 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17232 uint32_t IntBits = IntTy.getSizeInBits();
17233 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17234 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17254 int32_t
C = IntVal.exactLogBase2();
17255 if (
C == -1 ||
C == 0 ||
C > 32)
17261 if (IntBits < FloatBits)
17263 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17265 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17266 : Intrinsic::arm_neon_vcvtfxu2fp;
17274 if (!ST->hasMVEIntegerOps())
17278 EVT ResVT =
N->getValueType(0);
17306 EVT AVT =
A.getValueType();
17312 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17313 EVT AVT =
A.getValueType();
17323 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17324 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17327 if (ExtTypeMatches(
A, ExtTypes))
17328 return ExtendIfNeeded(
A, ExtendCode);
17331 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17341 if (ExtTypeMatches(
A, ExtTypes))
17342 return ExtendIfNeeded(
A, ExtendCode);
17345 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17355 if (ResVT != RetTy)
17358 if (
Mul->getOpcode() == ExtendCode &&
17359 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17361 Mul =
Mul->getOperand(0);
17370 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17371 A = ExtendIfNeeded(
A, ExtendCode);
17372 B = ExtendIfNeeded(
B, ExtendCode);
17377 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17390 if (
Mul->getOpcode() == ExtendCode &&
17391 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17393 Mul =
Mul->getOperand(0);
17402 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17403 A = ExtendIfNeeded(
A, ExtendCode);
17404 B = ExtendIfNeeded(
B, ExtendCode);
17415 EVT VT =
Ops[0].getValueType();
17416 if (VT == MVT::v16i8) {
17417 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17418 "Unexpected illegal long reduction opcode");
17419 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17431 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17444 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17446 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17447 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17449 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17450 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17452 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17455 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17458 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17462 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17465 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17468 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17471 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17474 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17477 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17480 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17482 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17484 return Create64bitNode(ARMISD::VADDLVs, {
A});
17486 return Create64bitNode(ARMISD::VADDLVu, {
A});
17489 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17492 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17495 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17497 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17499 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17501 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17504 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17507 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17514 Op =
Op->getOperand(1);
17516 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17518 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17535 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17537 if (!Shuf || !Shuf->getOperand(1).isUndef())
17542 APInt SetElts(Mask.size(), 0);
17543 for (
int E : Mask) {
17551 if (
N->getNumOperands() != VecOp + 1) {
17553 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17559 if (
Op.getValueType().isVector())
17560 Ops.push_back(
Op.getOperand(0));
17571 unsigned IsTop =
N->getConstantOperandVal(2);
17578 if (Op0->
isUndef() && !IsTop)
17583 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17584 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17592 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17594 APInt Op0DemandedElts =
17595 IsTop ? Op1DemandedElts
17610 unsigned IsTop =
N->getConstantOperandVal(2);
17612 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17613 APInt Op0DemandedElts =
17625 EVT VT =
N->getValueType(0);
17632 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17633 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17637 LHS.getOperand(0),
RHS.getOperand(0));
17652 int ShiftAmt =
C->getSExtValue();
17653 if (ShiftAmt == 0) {
17659 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17660 unsigned NewOpcode =
17661 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17676 unsigned IntNo =
N->getConstantOperandVal(0);
17687 case Intrinsic::arm_neon_vshifts:
17688 case Intrinsic::arm_neon_vshiftu:
17689 case Intrinsic::arm_neon_vrshifts:
17690 case Intrinsic::arm_neon_vrshiftu:
17691 case Intrinsic::arm_neon_vrshiftn:
17692 case Intrinsic::arm_neon_vqshifts:
17693 case Intrinsic::arm_neon_vqshiftu:
17694 case Intrinsic::arm_neon_vqshiftsu:
17695 case Intrinsic::arm_neon_vqshiftns:
17696 case Intrinsic::arm_neon_vqshiftnu:
17697 case Intrinsic::arm_neon_vqshiftnsu:
17698 case Intrinsic::arm_neon_vqrshiftns:
17699 case Intrinsic::arm_neon_vqrshiftnu:
17700 case Intrinsic::arm_neon_vqrshiftnsu: {
17701 EVT VT =
N->getOperand(1).getValueType();
17703 unsigned VShiftOpc = 0;
17706 case Intrinsic::arm_neon_vshifts:
17707 case Intrinsic::arm_neon_vshiftu:
17709 VShiftOpc = ARMISD::VSHLIMM;
17712 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17713 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17714 : ARMISD::VSHRuIMM);
17719 case Intrinsic::arm_neon_vrshifts:
17720 case Intrinsic::arm_neon_vrshiftu:
17725 case Intrinsic::arm_neon_vqshifts:
17726 case Intrinsic::arm_neon_vqshiftu:
17731 case Intrinsic::arm_neon_vqshiftsu:
17736 case Intrinsic::arm_neon_vrshiftn:
17737 case Intrinsic::arm_neon_vqshiftns:
17738 case Intrinsic::arm_neon_vqshiftnu:
17739 case Intrinsic::arm_neon_vqshiftnsu:
17740 case Intrinsic::arm_neon_vqrshiftns:
17741 case Intrinsic::arm_neon_vqrshiftnu:
17742 case Intrinsic::arm_neon_vqrshiftnsu:
17754 case Intrinsic::arm_neon_vshifts:
17755 case Intrinsic::arm_neon_vshiftu:
17758 case Intrinsic::arm_neon_vrshifts:
17759 VShiftOpc = ARMISD::VRSHRsIMM;
17761 case Intrinsic::arm_neon_vrshiftu:
17762 VShiftOpc = ARMISD::VRSHRuIMM;
17764 case Intrinsic::arm_neon_vrshiftn:
17765 VShiftOpc = ARMISD::VRSHRNIMM;
17767 case Intrinsic::arm_neon_vqshifts:
17768 VShiftOpc = ARMISD::VQSHLsIMM;
17770 case Intrinsic::arm_neon_vqshiftu:
17771 VShiftOpc = ARMISD::VQSHLuIMM;
17773 case Intrinsic::arm_neon_vqshiftsu:
17774 VShiftOpc = ARMISD::VQSHLsuIMM;
17776 case Intrinsic::arm_neon_vqshiftns:
17777 VShiftOpc = ARMISD::VQSHRNsIMM;
17779 case Intrinsic::arm_neon_vqshiftnu:
17780 VShiftOpc = ARMISD::VQSHRNuIMM;
17782 case Intrinsic::arm_neon_vqshiftnsu:
17783 VShiftOpc = ARMISD::VQSHRNsuIMM;
17785 case Intrinsic::arm_neon_vqrshiftns:
17786 VShiftOpc = ARMISD::VQRSHRNsIMM;
17788 case Intrinsic::arm_neon_vqrshiftnu:
17789 VShiftOpc = ARMISD::VQRSHRNuIMM;
17791 case Intrinsic::arm_neon_vqrshiftnsu:
17792 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17797 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17798 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17801 case Intrinsic::arm_neon_vshiftins: {
17802 EVT VT =
N->getOperand(1).getValueType();
17804 unsigned VShiftOpc = 0;
17807 VShiftOpc = ARMISD::VSLIIMM;
17808 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17809 VShiftOpc = ARMISD::VSRIIMM;
17815 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17816 N->getOperand(1),
N->getOperand(2),
17820 case Intrinsic::arm_neon_vqrshifts:
17821 case Intrinsic::arm_neon_vqrshiftu:
17825 case Intrinsic::arm_neon_vbsl: {
17827 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17828 N->getOperand(2),
N->getOperand(3));
17830 case Intrinsic::arm_mve_vqdmlah:
17831 case Intrinsic::arm_mve_vqdmlash:
17832 case Intrinsic::arm_mve_vqrdmlah:
17833 case Intrinsic::arm_mve_vqrdmlash:
17834 case Intrinsic::arm_mve_vmla_n_predicated:
17835 case Intrinsic::arm_mve_vmlas_n_predicated:
17836 case Intrinsic::arm_mve_vqdmlah_predicated:
17837 case Intrinsic::arm_mve_vqdmlash_predicated:
17838 case Intrinsic::arm_mve_vqrdmlah_predicated:
17839 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17844 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17851 case Intrinsic::arm_mve_minv:
17852 case Intrinsic::arm_mve_maxv:
17853 case Intrinsic::arm_mve_minav:
17854 case Intrinsic::arm_mve_maxav:
17855 case Intrinsic::arm_mve_minv_predicated:
17856 case Intrinsic::arm_mve_maxv_predicated:
17857 case Intrinsic::arm_mve_minav_predicated:
17858 case Intrinsic::arm_mve_maxav_predicated: {
17861 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17868 case Intrinsic::arm_mve_addv: {
17871 bool Unsigned =
N->getConstantOperandVal(2);
17872 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17876 case Intrinsic::arm_mve_addlv:
17877 case Intrinsic::arm_mve_addlv_predicated: {
17880 bool Unsigned =
N->getConstantOperandVal(2);
17881 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17882 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17883 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17886 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17888 Ops.push_back(
N->getOperand(i));
17901 EVT VT =
Y.getValueType();
17904 if (Subtarget->hasMVEIntegerOps())
17906 if (Subtarget->hasNEON())
17920 EVT VT =
N->getValueType(0);
17922 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17923 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17924 N->getOperand(0)->hasOneUse()) {
17941 if (AndMask == 255 || AndMask == 65535)
17945 if (MaskedBits > ShiftAmt) {
17960 if (ST->hasMVEIntegerOps())
17965 switch (
N->getOpcode()) {
17971 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17978 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17979 unsigned VShiftOpc =
17980 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17982 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17998 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
18001 EVT FromVT = LD->getValueType(0);
18002 EVT ToVT =
N->getValueType(0);
18009 unsigned NumElements = 0;
18010 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
18012 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
18014 if (NumElements == 0 ||
18024 SDValue BasePtr = LD->getBasePtr();
18025 Align Alignment = LD->getBaseAlign();
18046 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18047 Alignment, MMOFlags, AAInfo);
18053 if (FromEltVT == MVT::f16) {
18056 for (
unsigned i = 0; i < Loads.
size(); i++) {
18058 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
18077 EVT VT =
N->getValueType(0);
18084 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
18091 if (VT == MVT::i32 &&
18092 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
18097 switch (
N->getOpcode()) {
18100 Opc = ARMISD::VGETLANEs;
18104 Opc = ARMISD::VGETLANEu;
18111 if (ST->hasMVEIntegerOps())
18129 Ops.push_back(Ext);
18139 if (ST->hasMVEFloatOps())
18150 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
18154 EVT VT =
Op.getValueType();
18157 if (VT != MVT::i32 ||
18173 APInt MaxC = Max.getConstantOperandAPInt(1);
18174 if (MaxC.
sgt(MinC))
18181 if ((MinC + 1).isPowerOf2()) {
18203 APInt Width = MinC - MaxC + 1;
18206 unsigned SatBit = Width.
logBase2() - 1;
18224 EVT VT =
N->getValueType(0);
18227 if (VT == MVT::i32)
18230 if (!ST->hasMVEIntegerOps())
18236 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18239 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18247 if (VT == MVT::v4i32)
18248 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18250 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18257 MaxC != ~SaturateC)
18262 if (IsSignedSaturate(
N, N0.
getNode())) {
18265 if (VT == MVT::v4i32) {
18266 HalfVT = MVT::v8i16;
18267 ExtVT = MVT::v4i16;
18269 HalfVT = MVT::v16i8;
18284 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18290 if (VT == MVT::v4i32)
18291 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18293 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18302 if (IsUnsignedSaturate(
N)) {
18306 if (VT == MVT::v4i32) {
18307 HalfVT = MVT::v8i16;
18308 ExtConst = 0x0000FFFF;
18310 HalfVT = MVT::v16i8;
18332 const APInt *CV = &
C->getAPIntValue();
18389 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18396 if ((OrCI &
Known.Zero) != OrCI)
18402 EVT VT =
X.getValueType();
18403 unsigned BitInX = AndC->
logBase2();
18411 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18412 BitInY < NumActiveBits; ++BitInY) {
18413 if (OrCI[BitInY] == 0)
18416 Mask.setBit(BitInY);
18417 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18433 switch (
N->getOpcode()) {
18448 if (Const->isZero())
18450 else if (Const->isOne())
18458 unsigned IntOp =
N.getConstantOperandVal(1);
18459 if (IntOp != Intrinsic::test_start_loop_iterations &&
18460 IntOp != Intrinsic::loop_decrement_reg)
18486 bool Negate =
false;
18492 Cond =
N->getOperand(1);
18493 Dest =
N->getOperand(2);
18497 Cond =
N->getOperand(2);
18498 Dest =
N->getOperand(4);
18500 if (!Const->isOne() && !Const->isZero())
18502 Imm = Const->getZExtValue();
18530 assert((IsTrueIfZero(CC,
Imm) || IsFalseIfZero(CC,
Imm)) &&
18531 "unsupported condition");
18536 unsigned IntOp =
Int->getConstantOperandVal(1);
18537 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18538 "expected single br user");
18539 SDNode *Br = *
N->user_begin();
18549 if (IntOp == Intrinsic::test_start_loop_iterations) {
18551 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18553 if (IsTrueIfZero(CC,
Imm)) {
18555 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18559 UpdateUncondBr(Br, Dest, DAG);
18561 SDValue Ops[] = {Chain, Setup, OtherTarget};
18562 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18574 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18582 if (
Target == OtherTarget)
18583 UpdateUncondBr(Br, Dest, DAG);
18589 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18598 if (Cmp.getOpcode() != ARMISD::CMPZ)
18603 SDValue LHS = Cmp.getOperand(0);
18604 SDValue RHS = Cmp.getOperand(1);
18613 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18614 LHS->getOperand(0)->hasOneUse() &&
18618 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18630 EVT VT =
N->getValueType(0);
18631 SDValue FalseVal =
N->getOperand(0);
18632 SDValue TrueVal =
N->getOperand(1);
18640 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18647 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18650 if (Cmp.getOpcode() != ARMISD::CMPZ)
18654 SDValue LHS = Cmp.getOperand(0);
18655 SDValue RHS = Cmp.getOperand(1);
18659 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18683 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18684 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18685 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18688 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18693 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18696 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18697 LHS->getOperand(2), LHS->getOperand(3));
18707 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18711 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18713 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18722 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18755 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18767 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18787 const APInt *TrueConst;
18788 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18789 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18790 FalseVal.getOperand(1) == RHS) ||
18794 unsigned ShiftAmount = TrueConst->
logBase2();
18809 if (
Known.Zero == 0xfffffffe)
18812 else if (
Known.Zero == 0xffffff00)
18815 else if (
Known.Zero == 0xffff0000)
18828 EVT DstVT =
N->getValueType(0);
18831 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18832 EVT SrcVT = Src.getValueType();
18834 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18839 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18840 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18841 Src.getValueType().getScalarSizeInBits())
18842 Src = Src.getOperand(0);
18846 EVT SrcVT = Src.getValueType();
18847 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18848 Src.getOpcode() == ARMISD::VMVNIMM ||
18849 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18852 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18866 EVT VT =
N->getValueType(0);
18874 if (
N->getNumOperands() == 2 &&
18878 N->getOperand(0).getOperand(1),
18879 N->getOperand(1).getOperand(0),
18880 N->getOperand(1).getOperand(1));
18883 if (
N->getNumOperands() == 2 &&
18889 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18890 S0->getOperand(1) ==
S1->getOperand(1)) {
18893 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18897 ARMISD::VMOVN,
DL, VT,
18898 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18899 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18903 ARMISD::VMOVN,
DL, VT,
18904 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18905 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18913 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18914 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18915 (Op.getOpcode() == ISD::BITCAST &&
18916 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18919 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18921 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18939 int NumIns =
N->getNumOperands();
18940 assert((NumIns == 2 || NumIns == 4) &&
18941 "Expected 2 or 4 inputs to an MVETrunc");
18943 if (
N->getNumOperands() == 4)
18947 for (
int I = 0;
I < NumIns;
I++) {
18949 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18954 Ptr, MPI, StoreVT,
Align(4));
18969 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18972 EVT FromVT = LD->getMemoryVT();
18973 EVT ToVT =
N->getValueType(0);
18980 unsigned NumElements = 0;
18981 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18983 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18985 assert(NumElements != 0);
18991 LD->getExtensionType() != NewExtType)
18998 SDValue BasePtr = LD->getBasePtr();
18999 Align Alignment = LD->getBaseAlign();
19018 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
19019 Alignment, MMOFlags, AAInfo);
19035 EVT VT =
N->getValueType(0);
19037 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
19038 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
19040 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19042 auto Extend = [&](
SDValue V) {
19051 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
19052 SDValue Ext = Extend(
N->getOperand(0));
19060 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
19061 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
19065 auto CheckInregMask = [&](
int Start,
int Offset) {
19067 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
19073 if (CheckInregMask(0, 0))
19075 else if (CheckInregMask(0, 1))
19076 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19077 else if (CheckInregMask(0, Mask.size()))
19079 else if (CheckInregMask(0, Mask.size() + 1))
19080 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19085 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19089 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19091 if (V0.getNode() !=
N ||
V1.getNode() !=
N)
19096 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
19107 int NumOuts =
N->getNumValues();
19108 assert((NumOuts == 2 || NumOuts == 4) &&
19109 "Expected 2 or 4 outputs to an MVEEXT");
19110 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19112 if (
N->getNumOperands() == 4)
19118 StackPtr, MPI,
Align(4));
19121 for (
int I = 0;
I < NumOuts;
I++) {
19123 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
19124 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
19129 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
19138 switch (
N->getOpcode()) {
19198 case ARMISD::BRCOND:
19202 case ARMISD::CSINC:
19203 case ARMISD::CSINV:
19204 case ARMISD::CSNEG:
19217 case ARMISD::PREDICATE_CAST:
19219 case ARMISD::VECTOR_REG_CAST:
19230 case ARMISD::VADDVs:
19231 case ARMISD::VADDVu:
19232 case ARMISD::VADDLVs:
19233 case ARMISD::VADDLVu:
19234 case ARMISD::VADDLVAs:
19235 case ARMISD::VADDLVAu:
19236 case ARMISD::VMLAVs:
19237 case ARMISD::VMLAVu:
19238 case ARMISD::VMLALVs:
19239 case ARMISD::VMLALVu:
19240 case ARMISD::VMLALVAs:
19241 case ARMISD::VMLALVAu:
19243 case ARMISD::VMOVN:
19245 case ARMISD::VQMOVNs:
19246 case ARMISD::VQMOVNu:
19248 case ARMISD::VQDMULH:
19254 case ARMISD::SMULWB: {
19255 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19261 case ARMISD::SMULWT: {
19262 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19268 case ARMISD::SMLALBB:
19269 case ARMISD::QADD16b:
19270 case ARMISD::QSUB16b:
19271 case ARMISD::UQADD16b:
19272 case ARMISD::UQSUB16b: {
19273 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19280 case ARMISD::SMLALBT: {
19281 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19283 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19290 case ARMISD::SMLALTB: {
19291 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19293 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19300 case ARMISD::SMLALTT: {
19301 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19308 case ARMISD::QADD8b:
19309 case ARMISD::QSUB8b:
19310 case ARMISD::UQADD8b:
19311 case ARMISD::UQSUB8b: {
19312 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19320 if (
N->getOperand(1) ==
N->getOperand(2))
19321 return N->getOperand(1);
19325 switch (
N->getConstantOperandVal(1)) {
19326 case Intrinsic::arm_neon_vld1:
19327 case Intrinsic::arm_neon_vld1x2:
19328 case Intrinsic::arm_neon_vld1x3:
19329 case Intrinsic::arm_neon_vld1x4:
19330 case Intrinsic::arm_neon_vld2:
19331 case Intrinsic::arm_neon_vld3:
19332 case Intrinsic::arm_neon_vld4:
19333 case Intrinsic::arm_neon_vld2lane:
19334 case Intrinsic::arm_neon_vld3lane:
19335 case Intrinsic::arm_neon_vld4lane:
19336 case Intrinsic::arm_neon_vld2dup:
19337 case Intrinsic::arm_neon_vld3dup:
19338 case Intrinsic::arm_neon_vld4dup:
19339 case Intrinsic::arm_neon_vst1:
19340 case Intrinsic::arm_neon_vst1x2:
19341 case Intrinsic::arm_neon_vst1x3:
19342 case Intrinsic::arm_neon_vst1x4:
19343 case Intrinsic::arm_neon_vst2:
19344 case Intrinsic::arm_neon_vst3:
19345 case Intrinsic::arm_neon_vst4:
19346 case Intrinsic::arm_neon_vst2lane:
19347 case Intrinsic::arm_neon_vst3lane:
19348 case Intrinsic::arm_neon_vst4lane:
19350 case Intrinsic::arm_mve_vld2q:
19351 case Intrinsic::arm_mve_vld4q:
19352 case Intrinsic::arm_mve_vst2q:
19353 case Intrinsic::arm_mve_vst4q:
19370 unsigned *
Fast)
const {
19376 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19379 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19381 if (AllowsUnaligned) {
19383 *
Fast = Subtarget->hasV7Ops();
19388 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19392 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19399 if (!Subtarget->hasMVEIntegerOps())
19403 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19404 Ty == MVT::v2i1)) {
19412 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19428 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19429 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19430 Ty == MVT::v2f64) {
19443 if ((
Op.isMemcpyOrMemmove() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19444 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19446 if (
Op.size() >= 16 &&
19452 }
else if (
Op.size() >= 8 &&
19469 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19471 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19473 return (SrcBits == 64 && DestBits == 32);
19482 return (SrcBits == 64 && DestBits == 32);
19518 return Subtarget->hasFullFP16();
19525 if (!Subtarget->hasMVEIntegerOps())
19544 if (Ld->isExpandingLoad())
19548 if (Subtarget->hasMVEIntegerOps())
19561 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19593bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19595 if (Subtarget->useSoftFloat())
19604 return Subtarget->hasMVEFloatOps();
19622 unsigned Scale = 1;
19639 if ((V & (Scale - 1)) != 0)
19648 if (VT.
isVector() && Subtarget->hasNEON())
19651 !Subtarget->hasMVEFloatOps())
19654 bool IsNeg =
false;
19660 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19663 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19679 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19685 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19715 default:
return false;
19734 int Scale = AM.
Scale;
19739 default:
return false;
19747 Scale = Scale & ~1;
19748 return Scale == 2 || Scale == 4 || Scale == 8;
19765 if (Scale & 1)
return false;
19772 const int Scale = AM.
Scale;
19782 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19798 switch (AM.
Scale) {
19809 if (Subtarget->isThumb1Only())
19812 if (Subtarget->isThumb2())
19815 int Scale = AM.
Scale;
19817 default:
return false;
19821 if (Scale < 0) Scale = -Scale;
19829 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19842 if (Scale & 1)
return false;
19855 if (!Subtarget->isThumb())
19858 if (Subtarget->isThumb2())
19862 return Imm >= 0 &&
Imm <= 255;
19872 if (!Subtarget->isThumb())
19874 if (Subtarget->isThumb2())
19877 return AbsImm <= 255;
19912 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19916 int RHSC = (int)
RHS->getZExtValue();
19917 if (RHSC < 0 && RHSC > -256) {
19927 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19930 int RHSC = (int)
RHS->getZExtValue();
19931 if (RHSC < 0 && RHSC > -0x1000) {
19973 int RHSC = (int)
RHS->getZExtValue();
19974 if (RHSC < 0 && RHSC > -0x100) {
19979 }
else if (RHSC > 0 && RHSC < 0x100) {
19990 bool isSEXTLoad,
bool IsMasked,
bool isLE,
20001 bool CanChangeType = isLE && !IsMasked;
20004 int RHSC = (int)
RHS->getZExtValue();
20006 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
20007 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
20012 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
20023 if (VT == MVT::v4i16) {
20024 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
20026 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
20027 if (IsInRange(RHSC, 0x80, 1))
20029 }
else if (Alignment >= 4 &&
20030 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
20031 IsInRange(RHSC, 0x80, 4))
20033 else if (Alignment >= 2 &&
20034 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
20035 IsInRange(RHSC, 0x80, 2))
20037 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
20050 if (Subtarget->isThumb1Only())
20057 bool isSEXTLoad =
false;
20058 bool IsMasked =
false;
20060 Ptr = LD->getBasePtr();
20061 VT = LD->getMemoryVT();
20062 Alignment = LD->getAlign();
20063 AS = LD->getAddressSpace();
20066 Ptr = ST->getBasePtr();
20067 VT = ST->getMemoryVT();
20068 Alignment = ST->getAlign();
20069 AS = ST->getAddressSpace();
20071 Ptr = LD->getBasePtr();
20072 VT = LD->getMemoryVT();
20073 Alignment = LD->getAlign();
20074 AS = LD->getAddressSpace();
20078 Ptr = ST->getBasePtr();
20079 VT = ST->getMemoryVT();
20080 Alignment = ST->getAlign();
20081 AS = ST->getAddressSpace();
20096 bool isLegal =
false;
20098 isLegal = Subtarget->hasMVEIntegerOps() &&
20100 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
20101 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
20103 if (Subtarget->isThumb2())
20128 bool isSEXTLoad =
false, isNonExt;
20129 bool IsMasked =
false;
20131 VT = LD->getMemoryVT();
20132 Ptr = LD->getBasePtr();
20133 Alignment = LD->getAlign();
20137 VT = ST->getMemoryVT();
20138 Ptr = ST->getBasePtr();
20139 Alignment = ST->getAlign();
20140 isNonExt = !ST->isTruncatingStore();
20142 VT = LD->getMemoryVT();
20143 Ptr = LD->getBasePtr();
20144 Alignment = LD->getAlign();
20149 VT = ST->getMemoryVT();
20150 Ptr = ST->getBasePtr();
20151 Alignment = ST->getAlign();
20152 isNonExt = !ST->isTruncatingStore();
20157 if (Subtarget->isThumb1Only()) {
20160 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
20161 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
20164 if (!RHS || RHS->getZExtValue() != 4)
20166 if (Alignment <
Align(4))
20170 Base =
Op->getOperand(0);
20176 bool isLegal =
false;
20178 isLegal = Subtarget->hasMVEIntegerOps() &&
20183 if (Subtarget->isThumb2())
20197 !Subtarget->isThumb2())
20211 const APInt &DemandedElts,
20213 unsigned Depth)
const {
20216 switch (
Op.getOpcode()) {
20223 if (
Op.getResNo() == 0) {
20234 case ARMISD::CMOV: {
20237 if (
Known.isUnknown())
20249 case Intrinsic::arm_ldaex:
20250 case Intrinsic::arm_ldrex: {
20258 case ARMISD::BFI: {
20265 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20266 Known.Zero &= Mask;
20270 case ARMISD::VGETLANEs:
20271 case ARMISD::VGETLANEu: {
20272 const SDValue &SrcSV =
Op.getOperand(0);
20278 "VGETLANE index out of bounds");
20283 EVT VT =
Op.getValueType();
20289 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20297 case ARMISD::VMOVrh: {
20303 case ARMISD::CSINC:
20304 case ARMISD::CSINV:
20305 case ARMISD::CSNEG: {
20313 if (
Op.getOpcode() == ARMISD::CSINC)
20316 else if (
Op.getOpcode() == ARMISD::CSINV)
20318 else if (
Op.getOpcode() == ARMISD::CSNEG)
20325 case ARMISD::VORRIMM:
20326 case ARMISD::VBICIMM: {
20327 unsigned Encoded =
Op.getConstantOperandVal(1);
20328 unsigned DecEltBits = 0;
20331 unsigned EltBits =
Op.getScalarValueSizeInBits();
20332 if (EltBits != DecEltBits) {
20341 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20342 APInt Imm(DecEltBits, DecodedVal);
20353 if (!Subtarget->isThumb())
20370 if (
Imm == 0 ||
Imm == ~0U)
20373 unsigned Opc =
Op.getOpcode();
20375 EVT VT =
Op.getValueType();
20377 unsigned ShrunkImm =
Imm & Demanded;
20378 unsigned ExpandedImm =
Imm | ~Demanded;
20380 auto IsLegalImm = [ShrunkImm, ExpandedImm](
unsigned CandidateImm) ->
bool {
20381 return (ShrunkImm & CandidateImm) == ShrunkImm &&
20382 (~ExpandedImm & CandidateImm) == 0;
20384 auto UseImm = [
Imm,
Opc,
Op, VT, &TLO](
unsigned NewImm) ->
bool {
20396 if (ShrunkImm == 0) {
20397 ++NumOptimizedImms;
20398 return UseImm(ShrunkImm);
20404 if (ExpandedImm == ~0U) {
20405 ++NumOptimizedImms;
20406 return UseImm(ExpandedImm);
20414 if (IsLegalImm(0xFF)) {
20415 ++NumOptimizedImms;
20416 return UseImm(0xFF);
20419 if (IsLegalImm(0xFFFF)) {
20420 ++NumOptimizedImms;
20421 return UseImm(0xFFFF);
20435 ++NumOptimizedImms;
20436 return UseImm(ShrunkImm);
20444 if ((~ExpandedImm) < 256) {
20445 ++NumOptimizedImms;
20446 return UseImm(ExpandedImm);
20452 !Subtarget->hasV6Ops()) {
20453 ++NumOptimizedImms;
20454 return UseImm(ExpandedImm);
20473 EVT VT =
Op.getValueType();
20488 switch (
Op.getOpcode()) {
20499 unsigned Imm =
C->getZExtValue();
20506 unsigned Depth)
const {
20507 unsigned Opc =
Op.getOpcode();
20511 case ARMISD::LSRL: {
20515 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20517 unsigned ShAmt =
Op->getConstantOperandVal(2);
20527 case ARMISD::VBICIMM: {
20529 unsigned ModImm =
Op.getConstantOperandVal(1);
20530 unsigned EltBits = 0;
20532 if ((OriginalDemandedBits & Mask) == 0)
20538 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
20553 if (!Subtarget->hasVFP2Base())
20557 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20569 unsigned S = Constraint.
size();
20571 switch (Constraint[0]) {
20583 }
else if (S == 2) {
20584 switch (Constraint[0]) {
20601 Value *CallOperandVal =
info.CallOperandVal;
20604 if (!CallOperandVal)
20608 switch (*constraint) {
20614 if (Subtarget->isThumb())
20629 if (PR == 0 || VT == MVT::Other)
20631 if (ARM::SPRRegClass.
contains(PR))
20632 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20633 if (ARM::DPRRegClass.
contains(PR))
20638using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20642 switch (Constraint.
size()) {
20645 switch (Constraint[0]) {
20647 if (Subtarget->isThumb())
20648 return RCPair(0U, &ARM::tGPRRegClass);
20649 return RCPair(0U, &ARM::GPRRegClass);
20651 if (Subtarget->isThumb())
20652 return RCPair(0U, &ARM::hGPRRegClass);
20655 if (Subtarget->isThumb1Only())
20656 return RCPair(0U, &ARM::tGPRRegClass);
20657 return RCPair(0U, &ARM::GPRRegClass);
20659 if (VT == MVT::Other)
20661 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20662 return RCPair(0U, &ARM::SPRRegClass);
20664 return RCPair(0U, &ARM::DPRRegClass);
20666 return RCPair(0U, &ARM::QPRRegClass);
20669 if (VT == MVT::Other)
20671 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20672 return RCPair(0U, &ARM::SPR_8RegClass);
20674 return RCPair(0U, &ARM::DPR_8RegClass);
20676 return RCPair(0U, &ARM::QPR_8RegClass);
20679 if (VT == MVT::Other)
20681 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20682 return RCPair(0U, &ARM::SPRRegClass);
20684 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20686 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20692 if (Constraint[0] ==
'T') {
20693 switch (Constraint[1]) {
20697 return RCPair(0U, &ARM::tGPREvenRegClass);
20699 return RCPair(0U, &ARM::tGPROddRegClass);
20708 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20709 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20712 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20713 return std::make_pair(
unsigned(ARM::LR),
getRegClassFor(MVT::i32));
20717 return {0,
nullptr};
20725 std::vector<SDValue> &
Ops,
20730 if (Constraint.
size() != 1)
20733 char ConstraintLetter = Constraint[0];
20734 switch (ConstraintLetter) {
20737 case 'I':
case 'J':
case 'K':
case 'L':
20738 case 'M':
case 'N':
case 'O':
20743 int64_t CVal64 =
C->getSExtValue();
20744 int CVal = (int) CVal64;
20747 if (CVal != CVal64)
20750 switch (ConstraintLetter) {
20754 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20755 if (CVal >= 0 && CVal <= 65535)
20759 if (Subtarget->isThumb1Only()) {
20762 if (CVal >= 0 && CVal <= 255)
20764 }
else if (Subtarget->isThumb2()) {
20778 if (Subtarget->isThumb1Only()) {
20783 if (CVal >= -255 && CVal <= -1)
20789 if (CVal >= -4095 && CVal <= 4095)
20795 if (Subtarget->isThumb1Only()) {
20802 }
else if (Subtarget->isThumb2()) {
20822 if (Subtarget->isThumb1Only()) {
20825 if (CVal >= -7 && CVal < 7)
20827 }
else if (Subtarget->isThumb2()) {
20847 if (Subtarget->isThumb1Only()) {
20850 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20856 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20862 if (Subtarget->isThumb1Only()) {
20864 if (CVal >= 0 && CVal <= 31)
20870 if (Subtarget->isThumb1Only()) {
20873 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20882 if (Result.getNode()) {
20883 Ops.push_back(Result);
20893 "Unhandled Opcode in getDivRemLibcall");
20899 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20900 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20901 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20902 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20911 "Unhandled Opcode in getDivRemArgList");
20915 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20916 EVT ArgVT =
N->getOperand(i).getValueType();
20921 Args.push_back(Entry);
20929 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20930 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20931 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20932 "Register-based DivRem lowering only");
20933 unsigned Opcode =
Op->getOpcode();
20935 "Invalid opcode for Div/Rem lowering");
20937 EVT VT =
Op->getValueType(0);
20959 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20960 : Subtarget->hasDivideInARMMode();
20961 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20962 Op->getSimpleValueType(0) == MVT::i32) {
20964 const SDValue Dividend =
Op->getOperand(0);
20965 const SDValue Divisor =
Op->getOperand(1);
20966 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20970 SDValue
Values[2] = {Div, Rem};
20989 if (
getTM().getTargetTriple().isOSWindows())
20992 TargetLowering::CallLoweringInfo CLI(DAG);
20996 Callee, std::move(Args))
21001 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
21002 return CallInfo.first;
21008 EVT VT =
N->getValueType(0);
21014 Result[0], Result[1]);
21018 std::vector<Type*> RetTyParams;
21019 Type *RetTyElement;
21029 RetTyParams.push_back(RetTyElement);
21030 RetTyParams.push_back(RetTyElement);
21045 if (
getTM().getTargetTriple().isOSWindows())
21052 Callee, std::move(Args))
21056 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
21059 SDNode *ResNode = CallResult.first.getNode();
21066 assert(
getTM().getTargetTriple().isOSWindows() &&
21067 "unsupported target platform");
21071 SDValue Chain =
Op.getOperand(0);
21072 SDValue
Size =
Op.getOperand(1);
21075 "no-stack-arg-probe")) {
21079 Chain =
SP.getValue(1);
21085 SDValue
Ops[2] = {
SP, Chain };
21096 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
21097 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
21102 SDValue
Ops[2] = { NewSP, Chain };
21107 bool IsStrict =
Op->isStrictFPOpcode();
21108 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21109 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21111 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
21112 "Unexpected type for custom-lowering FP_EXTEND");
21114 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21115 "With both FP DP and 16, any FP conversion is legal!");
21117 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
21118 "With FP16, 16 to 32 conversion is legal!");
21121 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
21126 Loc,
Op.getValueType(), SrcVal);
21140 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
21141 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
21142 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
21143 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
21144 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
21148 {DstVT, MVT::Other}, {Chain, SrcVal});
21155 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21156 "Unexpected type for custom-lowering FP_EXTEND");
21157 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21162 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
21166 bool IsStrict =
Op->isStrictFPOpcode();
21168 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21170 EVT DstVT =
Op.getValueType();
21172 if (DstVT == MVT::bf16) {
21173 if (Subtarget->hasBF16() && SrcVT == MVT::f32)
21178 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21181 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
21182 "Unexpected type for custom-lowering FP_ROUND");
21184 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21185 "With both FP DP and 16, any FP conversion is legal!");
21190 if (SrcSz == 32 && Subtarget->hasFP16())
21195 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21196 "Unexpected type for custom-lowering FP_ROUND");
21198 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
21200 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21212 if (v == 0xffffffff)
21224 bool ForCodeSize)
const {
21225 if (!Subtarget->hasVFP3Base())
21227 if (VT == MVT::f16 && Subtarget->hasFullFP16())
21229 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
21232 if (VT == MVT::f32)
21234 if (VT == MVT::f64 && Subtarget->hasFP64())
21247 case Intrinsic::arm_neon_vld1:
21248 case Intrinsic::arm_neon_vld2:
21249 case Intrinsic::arm_neon_vld3:
21250 case Intrinsic::arm_neon_vld4:
21251 case Intrinsic::arm_neon_vld2lane:
21252 case Intrinsic::arm_neon_vld3lane:
21253 case Intrinsic::arm_neon_vld4lane:
21254 case Intrinsic::arm_neon_vld2dup:
21255 case Intrinsic::arm_neon_vld3dup:
21256 case Intrinsic::arm_neon_vld4dup: {
21259 auto &
DL =
I.getDataLayout();
21260 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21262 Info.ptrVal =
I.getArgOperand(0);
21264 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21271 case Intrinsic::arm_neon_vld1x2:
21272 case Intrinsic::arm_neon_vld1x3:
21273 case Intrinsic::arm_neon_vld1x4: {
21276 auto &
DL =
I.getDataLayout();
21277 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21279 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
21281 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
21287 case Intrinsic::arm_neon_vst1:
21288 case Intrinsic::arm_neon_vst2:
21289 case Intrinsic::arm_neon_vst3:
21290 case Intrinsic::arm_neon_vst4:
21291 case Intrinsic::arm_neon_vst2lane:
21292 case Intrinsic::arm_neon_vst3lane:
21293 case Intrinsic::arm_neon_vst4lane: {
21296 auto &
DL =
I.getDataLayout();
21297 unsigned NumElts = 0;
21298 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21299 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21302 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21305 Info.ptrVal =
I.getArgOperand(0);
21307 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21314 case Intrinsic::arm_neon_vst1x2:
21315 case Intrinsic::arm_neon_vst1x3:
21316 case Intrinsic::arm_neon_vst1x4: {
21319 auto &
DL =
I.getDataLayout();
21320 unsigned NumElts = 0;
21321 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21322 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21325 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21328 Info.ptrVal =
I.getArgOperand(0);
21330 Info.align =
I.getParamAlign(0).valueOrOne();
21336 case Intrinsic::arm_mve_vld2q:
21337 case Intrinsic::arm_mve_vld4q: {
21341 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21343 Info.ptrVal =
I.getArgOperand(0);
21351 case Intrinsic::arm_mve_vst2q:
21352 case Intrinsic::arm_mve_vst4q: {
21355 Type *VecTy =
I.getArgOperand(1)->getType();
21356 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21358 Info.ptrVal =
I.getArgOperand(0);
21366 case Intrinsic::arm_mve_vldr_gather_base:
21367 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21369 Info.ptrVal =
nullptr;
21371 Info.align =
Align(1);
21376 case Intrinsic::arm_mve_vldr_gather_base_wb:
21377 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21379 Info.ptrVal =
nullptr;
21380 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21381 Info.align =
Align(1);
21386 case Intrinsic::arm_mve_vldr_gather_offset:
21387 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21389 Info.ptrVal =
nullptr;
21394 Info.align =
Align(1);
21399 case Intrinsic::arm_mve_vstr_scatter_base:
21400 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21402 Info.ptrVal =
nullptr;
21403 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21404 Info.align =
Align(1);
21409 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21410 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21412 Info.ptrVal =
nullptr;
21413 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21414 Info.align =
Align(1);
21419 case Intrinsic::arm_mve_vstr_scatter_offset:
21420 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21422 Info.ptrVal =
nullptr;
21427 Info.align =
Align(1);
21432 case Intrinsic::arm_ldaex:
21433 case Intrinsic::arm_ldrex: {
21434 auto &
DL =
I.getDataLayout();
21435 Type *ValTy =
I.getParamElementType(0);
21438 Info.ptrVal =
I.getArgOperand(0);
21440 Info.align =
DL.getABITypeAlign(ValTy);
21445 case Intrinsic::arm_stlex:
21446 case Intrinsic::arm_strex: {
21447 auto &
DL =
I.getDataLayout();
21448 Type *ValTy =
I.getParamElementType(1);
21451 Info.ptrVal =
I.getArgOperand(1);
21453 Info.align =
DL.getABITypeAlign(ValTy);
21458 case Intrinsic::arm_stlexd:
21459 case Intrinsic::arm_strexd:
21461 Info.memVT = MVT::i64;
21462 Info.ptrVal =
I.getArgOperand(2);
21464 Info.align =
Align(8);
21469 case Intrinsic::arm_ldaexd:
21470 case Intrinsic::arm_ldrexd:
21472 Info.memVT = MVT::i64;
21473 Info.ptrVal =
I.getArgOperand(0);
21475 Info.align =
Align(8);
21489 assert(Ty->isIntegerTy());
21491 unsigned Bits = Ty->getPrimitiveSizeInBits();
21492 if (Bits == 0 || Bits > 32)
21499 unsigned Index)
const {
21511 if (!Subtarget->hasDataBarrier()) {
21515 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21516 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21517 Builder.getInt32(0), Builder.getInt32(7),
21518 Builder.getInt32(10), Builder.getInt32(5)};
21519 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_mcr,
args);
21528 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_dmb, CDomain);
21549 if (Subtarget->preferISHSTBarriers())
21582 bool has64BitAtomicStore;
21583 if (Subtarget->isMClass())
21584 has64BitAtomicStore =
false;
21585 else if (Subtarget->isThumb())
21586 has64BitAtomicStore = Subtarget->hasV7Ops();
21588 has64BitAtomicStore = Subtarget->hasV6Ops();
21590 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21604 bool has64BitAtomicLoad;
21605 if (Subtarget->isMClass())
21606 has64BitAtomicLoad =
false;
21607 else if (Subtarget->isThumb())
21608 has64BitAtomicLoad = Subtarget->hasV7Ops();
21610 has64BitAtomicLoad = Subtarget->hasV6Ops();
21626 if (Subtarget->isMClass())
21627 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21628 else if (Subtarget->isThumb())
21629 hasAtomicRMW = Subtarget->hasV7Ops();
21631 hasAtomicRMW = Subtarget->hasV6Ops();
21632 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21656 bool HasAtomicCmpXchg;
21657 if (Subtarget->isMClass())
21658 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21659 else if (Subtarget->isThumb())
21660 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21662 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21664 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21671 return InsertFencesForAtomic;
21676 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21682 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21683 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21685 RTLIB::LibcallImpl SecurityCookieVar =
21686 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21687 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21688 SecurityCookieVar != RTLIB::Unsupported) {
21699 F->addParamAttr(0, Attribute::AttrKind::InReg);
21706 unsigned &
Cost)
const {
21708 if (!Subtarget->hasNEON())
21737 unsigned Opcode =
Op.getOpcode();
21739 case ARMISD::VORRIMM:
21740 case ARMISD::VBICIMM:
21744 Op, DemandedElts, DAG, Kind, ConsiderFlags,
Depth);
21748 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21752 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21757 if (!Subtarget->hasV7Ops())
21763 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21765 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21773 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21782 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21788 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21790 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21793 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21795 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21796 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21797 if (!Subtarget->isLittle())
21799 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21800 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21801 return Builder.CreateOr(
21802 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21806 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21807 CallInst *CI = Builder.CreateIntrinsicWithoutFolding(
Int, Tys, Addr);
21810 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21811 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21816 if (!Subtarget->hasV7Ops())
21818 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21824 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21832 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21835 Value *
Lo = Builder.CreateTrunc(Val, Int32Ty,
"lo");
21836 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32), Int32Ty,
"hi");
21837 if (!Subtarget->isLittle())
21839 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21842 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21846 CallInst *CI = Builder.CreateCall(
21847 Strex, {Builder.CreateZExtOrBitCast(
21857 return Subtarget->isMClass();
21865 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21872 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21875 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21883 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21891 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21894 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21899 if (Subtarget->hasNEON() && VecSize == 64)
21901 return VecSize % 128 == 0;
21905 if (Subtarget->hasNEON())
21907 if (Subtarget->hasMVEIntegerOps())
21927 "Invalid interleave factor");
21928 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21930 "Unmatched number of shufflevectors and indices");
21935 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21938 Type *EltTy = VecTy->getElementType();
21941 Align Alignment = LI->getAlign();
21959 Value *BaseAddr = LI->getPointerOperand();
21961 if (NumLoads > 1) {
21965 VecTy->getNumElements() / NumLoads);
21971 if (Subtarget->hasNEON()) {
21972 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21973 Type *Tys[] = {VecTy, PtrTy};
21974 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21975 Intrinsic::arm_neon_vld3,
21976 Intrinsic::arm_neon_vld4};
21979 Ops.push_back(BaseAddr);
21980 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21982 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21985 assert((Factor == 2 || Factor == 4) &&
21986 "expected interleave factor of 2 or 4 for MVE");
21988 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21989 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21990 Type *Tys[] = {VecTy, PtrTy};
21993 Ops.push_back(BaseAddr);
21994 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
22004 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
22008 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
22009 VecTy->getNumElements() * Factor);
22015 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
22017 unsigned Index = Indices[i];
22019 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
22023 SubVec = Builder.CreateIntToPtr(
22027 SubVecs[SV].push_back(SubVec);
22036 auto &SubVec = SubVecs[SVI];
22039 SVI->replaceAllUsesWith(WideVec);
22075 const APInt &GapMask)
const {
22077 "Invalid interleave factor");
22082 "Unexpected mask on store");
22085 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
22087 unsigned LaneLen = VecTy->getNumElements() / Factor;
22088 Type *EltTy = VecTy->getElementType();
22092 Align Alignment =
SI->getAlign();
22109 Type *IntTy =
DL.getIntPtrType(EltTy);
22114 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
22115 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
22121 Value *BaseAddr =
SI->getPointerOperand();
22123 if (NumStores > 1) {
22126 LaneLen /= NumStores;
22136 if (Subtarget->hasNEON()) {
22137 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
22138 Intrinsic::arm_neon_vst3,
22139 Intrinsic::arm_neon_vst4};
22140 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22141 Type *Tys[] = {PtrTy, SubVecTy};
22144 Ops.push_back(BaseAddr);
22146 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
22147 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
22149 assert((Factor == 2 || Factor == 4) &&
22150 "expected interleave factor of 2 or 4 for MVE");
22152 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
22153 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22154 Type *Tys[] = {PtrTy, SubVecTy};
22157 Ops.push_back(BaseAddr);
22159 for (
unsigned F = 0;
F < Factor;
F++) {
22160 Ops.push_back(Builder.getInt32(
F));
22161 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
22167 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
22170 if (StoreCount > 0)
22171 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
22172 BaseAddr, LaneLen * Factor);
22177 for (
unsigned i = 0; i < Factor; i++) {
22178 unsigned IdxI = StoreCount * LaneLen * Factor + i;
22179 if (Mask[IdxI] >= 0) {
22180 Shuffles.
push_back(Builder.CreateShuffleVector(
22183 unsigned StartMask = 0;
22184 for (
unsigned j = 1; j < LaneLen; j++) {
22185 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
22186 if (Mask[IdxJ * Factor + IdxI] >= 0) {
22187 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
22197 Shuffles.
push_back(Builder.CreateShuffleVector(
22218 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
22222 Members += SubMembers;
22228 Members += SubMembers * AT->getNumElements();
22229 }
else if (Ty->isFloatTy()) {
22234 }
else if (Ty->isDoubleTy()) {
22246 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
22248 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
22250 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
22263 return (Members > 0 && Members <= 4);
22269 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
22271 return ABITypeAlign;
22276 assert(StackAlign &&
"data layout string is missing stack alignment");
22277 return std::min(ABITypeAlign, *StackAlign);
22291 uint64_t Members = 0;
22295 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
22296 return IsHA || IsIntArray;
22319void ARMTargetLowering::insertCopiesSplitCSR(
22323 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22333 RC = &ARM::GPRRegClass;
22334 else if (ARM::DPRRegClass.
contains(*
I))
22335 RC = &ARM::DPRRegClass;
22345 assert(Entry->getParent()->getFunction().hasFnAttribute(
22346 Attribute::NoUnwind) &&
22347 "Function should be nounwind in insertCopiesSplitCSR!");
22348 Entry->addLiveIn(*
I);
22353 for (
auto *Exit : Exits)
22355 TII->get(TargetOpcode::COPY), *
I)
22366 return Subtarget->hasMVEIntegerOps();
22376 unsigned NumElements = VTy->getNumElements();
22383 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22384 return Subtarget->hasMVEFloatOps();
22389 return Subtarget->hasMVEIntegerOps() &&
22390 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22391 ScalarTy->isIntegerTy(32));
22395 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22406 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22408 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22410 if (TyWidth > 128) {
22411 int Stride = Ty->getNumElements() / 2;
22415 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22417 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22418 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22419 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22420 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22421 Value *LowerSplitAcc =
nullptr;
22422 Value *UpperSplitAcc =
nullptr;
22425 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22426 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22430 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22432 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22434 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22435 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22442 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22445 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22447 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22448 {ConstRotation, InputB, InputA});
22453 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22456 ConstRotation = ConstantInt::get(IntTy, 0);
22458 ConstRotation = ConstantInt::get(IntTy, 1);
22460 if (!ConstRotation)
22463 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22464 {ConstHalving, ConstRotation, InputA, InputB});
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static SDValue carryFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG, bool Invert)
static SDValue overflowFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue valueToCarryFlag(SDValue Value, SelectionDAG &DAG, bool Invert)
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static unsigned getCmpOperandFoldingProfit(SDValue Op, bool AllowExtend)
Returns how profitable it is to fold a comparison's operand's shift and/or extension operations.
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static bool optimizeLogicalImm(SDValue Op, unsigned Size, uint64_t Imm, const APInt &Demanded, TargetLowering::TargetLoweringOpt &TLO, unsigned NewOpc)
static bool isSafeSignedCMN(SDValue Op, SelectionDAG &DAG)
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static SDValue matchCSET(unsigned &Opcode, bool &InvertCond, SDValue TrueVal, SDValue FalseVal, const ARMSubtarget *Subtarget)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getInvertedARMCondCode(SDValue ARMcc, SelectionDAG &DAG)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static SDValue LowerADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG, unsigned Opcode, bool IsSigned)
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static int getNegationCost(SDValue Op)
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static bool isLegalLogicalImmediate(unsigned Imm, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static unsigned SelectPairHalf(unsigned Elements, ArrayRef< int > Mask, unsigned Index)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerTruncate(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformHWLoopCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformORCombineToShiftInsert(SelectionDAG &DAG, SDValue AndOp, SDValue ShiftOp, EVT VT, SDLoc dl)
static SDValue PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static constexpr roundingMode rmTowardZero
LLVM_ABI bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
unsigned logBase2() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool isOne() const
Determine if this is a value of 1.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
const ARMBaseRegisterInfo & getRegisterInfo() const
const uint32_t * getSjLjDispatchPreservedMask(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const uint32_t * getTLSCallPreservedMask(const MachineFunction &MF) const
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj, ARMCP::ARMCPModifier Modifier=ARMCP::no_modifier, bool AddCurrentAddress=false)
ARMConstantPoolValue - ARM specific constantpool value.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
int getVarArgsFrameIndex() const
int getPromotedConstpoolIncrease() const
SmallPtrSet< const GlobalVariable *, 2 > & getGlobalsPromotedToConstantPool()
void setArgumentStackToRestore(unsigned v)
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
void setPromotedConstpoolIncrease(int Sz)
bool isThumb1OnlyFunction() const
void setArgRegsSaveSize(unsigned s)
bool isCmseNSEntryFunction() const
void setReturnRegsCount(unsigned s)
void setVarArgsFrameIndex(int Index)
unsigned getArgRegsSaveSize() const
void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV)
Indicate to the backend that GV has had its storage changed to inside a constant pool.
void setIsSplitCSR(bool s)
void setArgumentStackSize(unsigned size)
unsigned getArgumentStackSize() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool isReadOnly(const GlobalValue *GV) const
unsigned getMaxSupportedInterleaveFactor() const override
Get the maximum supported factor for interleaved memory accesses.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
unsigned getNumInterleavedAccesses(VectorType *VecTy, const DataLayout &DL) const
Returns the number of interleaved accesses that will be generated when lowering accesses of the given...
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Align getABIAlignmentForCallingConv(Type *ArgTy, const DataLayout &DL) const override
Return the correct alignment for the current calling convention.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
bool shouldFoldConstantShiftPairToMask(const SDNode *N) const override
Return true if it is profitable to fold a pair of shifts into a mask.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override
Return true if it is profitable to combine an XOR of a logical shift to create a logical shift of NOT...
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const
PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
Value * createComplexDeinterleavingIR(IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, Value *Accumulator=nullptr) const override
Create the IR node for the given complex deinterleaving operation.
bool isComplexDeinterleavingSupported() const override
Does this target support complex deinterleaving.
SDValue PerformMVEExtCombine(SDNode *N, DAGCombinerInfo &DCI) const
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const override
Inserts necessary declarations for SSP (stack protection) purpose.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &OriginalDemandedBits, const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the value type to use for ISD::SETCC.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const override
Perform a store-conditional operation to Addr.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool isVarArg) const
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
isShuffleMaskLegal - Targets can use this to indicate that they only support some VECTOR_SHUFFLE oper...
Register getExceptionPointerRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
bool lowerInterleavedStore(Instruction *Store, Value *Mask, ShuffleVectorInst *SVI, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved store into a vstN intrinsic.
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
bool useLoadStackGuardNode(const Module &M) const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vldN intrinsic.
std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override
Return the largest legal super-reg register class of the register class for the specified type and it...
bool preferSelectsOverBooleanArithmetic(EVT VT) const override
Should we prefer selects to doing arithmetic on boolean types.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
Register getExceptionSelectorRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of EXTRACT_SUBVECTOR for this result type with this index.
CallingConv::ID getEffectiveCallingConv(CallingConv::ID CC, bool isVarArg) const
getEffectiveCallingConv - Get the effective calling convention, taking into account presence of float...
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
bool supportKCFIBundles() const override
Return true if the target supports kcfi operand bundles.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool isVarArg) const
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
allowsMisalignedMemoryAccesses - Returns true if the target allows unaligned memory accesses of the s...
bool isLegalInterleavedAccessType(unsigned Factor, FixedVectorType *VecTy, Align Alignment, const DataLayout &DL) const
Returns true if VecTy is a legal interleaved access type.
bool isVectorLoadExtDesirable(SDValue ExtVal) const override
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, unsigned &Cost) const override
Return true if the target can combine store(extractelement VectorTy,Idx).
bool useSoftFloat() const override
bool alignLoopsWithOptSize() const override
Should loops be aligned even when the function is marked OptSize (but not MinSize).
SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const
bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override
Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail ...
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
bool hasAndNotCompare(SDValue V) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT.
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
bool isFloatingPointOperation() const
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
The address of a basic block.
static constexpr BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
LLVM_ABI int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, uint32_t BitWidth) const
If this is a constant FP splat and the splatted constant FP is an exact power or 2,...
CCState - This class holds information needed while lowering arguments and return values.
void getInRegsParamInfo(unsigned InRegsParamRecordIndex, unsigned &BeginReg, unsigned &EndReg) const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
void rewindByValRegsInfo()
unsigned getInRegsParamsProcessed() const
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd)
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
unsigned getInRegsParamsCount() const
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
const APFloat & getValueAPF() const
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
MachineConstantPoolValue * getMachineCPVal() const
bool isMachineConstantPoolEntry() const
const Constant * getConstVal() const
LLVM_ABI Type * getType() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
MaybeAlign getStackAlignment() const
Returns the natural stack alignment, or MaybeAlign() if one wasn't specified.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
StringRef getInternalSymbolPrefix() const
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
Tracks which library functions to use for a particular subtarget or function.
CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const
Get the CallingConv that should be used for the specified libcall.
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Describe properties that are true of each instruction in the target description file.
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
bool is64BitVector() const
Return true if this is a 64-bit vector type.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI unsigned createJumpTableIndex(const std::vector< MachineBasicBlock * > &DestBBs)
createJumpTableIndex - Create a new jump table.
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
This class is used to represent an MLOAD node.
This class is used to represent an MSTORE node.
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
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.
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
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
Provides information about what library functions are available for the current target.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
ShiftLegalizationStrategy
Return the preferred strategy to legalize tihs SHIFT instruction, with ExpansionFactor being the recu...
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
const TargetMachine & getTargetMachine() const
virtual void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const
Inserts necessary declarations for SSP (stack protection) purpose.
void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked load does or does not work with the specified type and ind...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked store does or does not work with the specified type and in...
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
static StringRef getLibcallImplName(RTLIB::LibcallImpl Call)
Get the libcall routine name for the specified libcall implementation.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool expandDIVREMByConstant(SDNode *N, SmallVectorImpl< SDValue > &Result, EVT HiLoVT, SelectionDAG &DAG, SDValue LL=SDValue(), SDValue LH=SDValue()) const
Attempt to expand an n-bit div/rem/divrem by constant using an n/2-bit algorithm.
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual ArrayRef< MCPhysReg > getRoundingControlRegisters() const
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
void setTypeIdForCallsiteInfo(const CallBase *CB, MachineFunction &MF, MachineFunction::CallSiteInfo &CSInfo) const
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
bool isOSWindows() const
Tests whether the OS is Windows.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
Base class of all SIMD vector types.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static CondCodes getOppositeCondition(CondCodes CC)
static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC)
getSwappedCondition - assume the flags are set by MI(a,b), return the condition code if we modify the...
@ SECREL
Thread Pointer Offset.
@ GOT_PREL
Thread Local Storage (General Dynamic Mode)
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
TOF
Target Operand Flag enum.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2Offset(unsigned AM2Opc)
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
AddrOpc getAM2Op(unsigned AM2Opc)
bool isBitFieldInvertedMask(unsigned v)
const unsigned FPStatusBits
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
const unsigned FPReservedBits
const unsigned RoundingBitsPos
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Swift
Calling convention for Swift.
@ ARM_APCS
ARM Procedure Calling Standard (obsolete, but still used on some targets).
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ ARM_AAPCS
ARM Architecture Procedure Calling Standard calling convention (aka EABI).
@ CXX_FAST_TLS
Used for access functions.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ ARM_AAPCS_VFP
Same as ARM_AAPCS, but uses hard floating point ABI.
@ C
The default llvm calling convention, compatible with C.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ POISON
POISON - A poison node.
@ SET_FPENV
Sets the current floating-point environment.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
@ FGETSIGN
INT = FGETSIGN(FP) - Return the sign bit of the specified floating point value as an integer 0/1 valu...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ RESET_FPENV
Set floating-point environment to default state.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SET_FPMODE
Sets the current dynamic floating-point control modes.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ EH_SJLJ_SETUP_DISPATCH
OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) The target initializes the dispatch table here.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ RESET_FPMODE
Sets default dynamic floating-point control modes.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ BR
Control flow instructions. These all have token chains.
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ BR_JT
BR_JT - Jumptable branch.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SMULO
Same for multiplication.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ SADDO_CARRY
Carry-using overflow-aware nodes for multiple precision addition and subtraction.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
const unsigned PerfectShuffleTable[6561+1]
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
@ SjLj
setjmp/longjmp based exceptions
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
UndefPoisonKind
Enumeration to track whether we are interested in Undef, Poison, or both.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
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.
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)