83#include "llvm/IR/IntrinsicsARM.h"
118#define DEBUG_TYPE "arm-isel"
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) {
339 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
340 for (
auto VT : FloatTypes) {
414 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
415 for (
auto VT : LongTypes) {
432 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
433 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
434 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
451 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
460 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
461 for (
auto VT : pTypes) {
512 RegInfo(Subtarget->getRegisterInfo()),
513 Itins(Subtarget->getInstrItineraryData()) {
519 const Triple &TT = TM.getTargetTriple();
521 if (Subtarget->isThumb1Only())
526 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
527 Subtarget->hasFPRegs()) {
536 if (!Subtarget->hasVFP2Base()) {
537 setAllExpand(MVT::f32);
543 if (!Subtarget->hasFP64()) {
544 setAllExpand(MVT::f64);
554 if (Subtarget->hasFullFP16()) {
569 if (Subtarget->hasBF16()) {
571 setAllExpand(MVT::bf16);
572 if (!Subtarget->hasFullFP16())
584 addAllExtLoads(VT, InnerVT,
Expand);
593 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
596 if (!Subtarget->hasV8_1MMainlineOps())
599 if (!Subtarget->isThumb1Only())
608 if (Subtarget->hasMVEIntegerOps())
609 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
612 if (Subtarget->hasLOB()) {
616 if (Subtarget->hasNEON()) {
617 addDRTypeForNEON(MVT::v2f32);
618 addDRTypeForNEON(MVT::v8i8);
619 addDRTypeForNEON(MVT::v4i16);
620 addDRTypeForNEON(MVT::v2i32);
621 addDRTypeForNEON(MVT::v1i64);
623 addQRTypeForNEON(MVT::v4f32);
624 addQRTypeForNEON(MVT::v2f64);
625 addQRTypeForNEON(MVT::v16i8);
626 addQRTypeForNEON(MVT::v8i16);
627 addQRTypeForNEON(MVT::v4i32);
628 addQRTypeForNEON(MVT::v2i64);
630 if (Subtarget->hasFullFP16()) {
631 addQRTypeForNEON(MVT::v8f16);
632 addDRTypeForNEON(MVT::v4f16);
635 if (Subtarget->hasBF16()) {
636 addQRTypeForNEON(MVT::v8bf16);
637 addDRTypeForNEON(MVT::v4bf16);
641 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
681 if (Subtarget->hasNEON()) {
722 ISD::FRINT, ISD::FTRUNC, ISD::FROUNDEVEN}) {
794 if (!Subtarget->hasVFP4Base()) {
803 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
812 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
821 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
829 if (Subtarget->hasMVEIntegerOps()) {
834 if (Subtarget->hasMVEFloatOps()) {
838 if (!Subtarget->hasFP64()) {
884 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
887 if (Subtarget->hasFullFP16()) {
895 if (!Subtarget->hasFP16()) {
924 if (!Subtarget->isThumb1Only()) {
949 if (Subtarget->hasDSP()) {
959 if (Subtarget->hasBaseDSP()) {
967 if (Subtarget->isThumb1Only()) {
971 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
972 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
987 if (Subtarget->hasMVEIntegerOps())
991 if (Subtarget->isThumb1Only()) {
997 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1011 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1020 if (Subtarget->hasPerfMon())
1024 if (!Subtarget->hasV6Ops())
1027 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1028 : Subtarget->hasDivideInARMMode();
1035 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1047 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1048 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1051 HasStandaloneRem =
false;
1078 if (TT.isOSWindows())
1085 InsertFencesForAtomic =
false;
1086 if (Subtarget->hasAnyDataBarrier() &&
1087 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1091 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1096 if (!Subtarget->hasAcquireRelease() ||
1099 InsertFencesForAtomic =
true;
1105 if (Subtarget->hasDataBarrier())
1106 InsertFencesForAtomic =
true;
1126 if (!InsertFencesForAtomic) {
1133 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1145 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1146 Subtarget->hasForced32BitAtomics()) {
1160 if (!Subtarget->hasV6Ops()) {
1166 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1167 !Subtarget->isThumb1Only()) {
1196 if (Subtarget->hasFullFP16()) {
1206 if (Subtarget->hasFullFP16())
1221 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1222 !Subtarget->isThumb1Only()) {
1229 if (!Subtarget->hasVFP4Base()) {
1235 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1237 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1245 if (!Subtarget->hasFP16()) {
1265 if (Subtarget->hasFPARMv8Base()) {
1267 {ISD::FFLOOR, ISD::FCEIL, ISD::FROUND,
1268 ISD::FTRUNC, ISD::FNEARBYINT, ISD::FRINT,
1269 ISD::FROUNDEVEN, ISD::FMINNUM, ISD::FMAXNUM,
1275 if (Subtarget->hasFP64())
1279 if (Subtarget->hasNEON()) {
1289 if (Subtarget->hasFullFP16()) {
1295 ISD::FCOS, ISD::FSIN, ISD::FSINCOS,
1296 ISD::FSINCOSPI, ISD::FMODF, ISD::FACOS,
1297 ISD::FASIN, ISD::FATAN, ISD::FATAN2,
1298 ISD::FCOSH, ISD::FSINH, ISD::FTANH,
1299 ISD::FTAN, ISD::FEXP, ISD::FEXP2,
1300 ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
1316 for (
auto Op : {ISD::FROUND, ISD::FROUNDEVEN, ISD::FTRUNC,
1317 ISD::FNEARBYINT, ISD::FRINT, ISD::FFLOOR,
1326 if (Subtarget->hasNEON()) {
1338 if (Subtarget->hasV8Ops()) {
1353 if (Subtarget->hasFullFP16()) {
1381 if (TT.isOSWindows()) {
1398 if (Subtarget->hasMVEIntegerOps())
1401 if (Subtarget->hasV6Ops())
1403 if (Subtarget->isThumb1Only())
1406 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1407 Subtarget->isThumb2()) {
1413 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1414 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1436 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1444 return Subtarget->useSoftFloat();
1448 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1461std::pair<const TargetRegisterClass *, uint8_t>
1472 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1473 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1474 RRC = &ARM::DPRRegClass;
1479 if (Subtarget->useNEONForSinglePrecisionFP())
1482 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1483 case MVT::v4f32:
case MVT::v2f64:
1484 RRC = &ARM::DPRRegClass;
1488 RRC = &ARM::DPRRegClass;
1492 RRC = &ARM::DPRRegClass;
1496 return std::make_pair(RRC,
Cost);
1505 if ((Subtarget->hasMVEIntegerOps() &&
1506 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1507 VT == MVT::v16i8)) ||
1508 (Subtarget->hasMVEFloatOps() &&
1509 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1523 if (Subtarget->hasNEON()) {
1524 if (VT == MVT::v4i64)
1525 return &ARM::QQPRRegClass;
1526 if (VT == MVT::v8i64)
1527 return &ARM::QQQQPRRegClass;
1529 if (Subtarget->hasMVEIntegerOps()) {
1530 if (VT == MVT::v4i64)
1531 return &ARM::MQQPRRegClass;
1532 if (VT == MVT::v8i64)
1533 return &ARM::MQQQQPRRegClass;
1542 Align &PrefAlign)
const {
1549 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1561 unsigned NumVals =
N->getNumValues();
1565 for (
unsigned i = 0; i != NumVals; ++i) {
1566 EVT VT =
N->getValueType(i);
1567 if (VT == MVT::Glue || VT == MVT::Other)
1573 if (!
N->isMachineOpcode())
1581 if (
MCID.getNumDefs() == 0)
1583 if (!Itins->isEmpty() &&
1584 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1598 return Const->getZExtValue() == 16;
1606 return Const->getZExtValue() == 16;
1614 return Const->getZExtValue() == 16;
1683 bool isVarArg)
const {
1702 if (!
getTM().isAAPCS_ABI())
1704 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1712 if (!
getTM().isAAPCS_ABI()) {
1713 if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() && !isVarArg)
1716 }
else if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() &&
1725 bool isVarArg)
const {
1726 return CCAssignFnForNode(CC,
false, isVarArg);
1730 bool isVarArg)
const {
1731 return CCAssignFnForNode(CC,
true, isVarArg);
1738 bool isVarArg)
const {
1739 switch (getEffectiveCallingConv(CC, isVarArg)) {
1765 if (Subtarget->hasFullFP16()) {
1766 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1770 Val = DAG.
getNode(ISD::BITCAST, dl, ValVT, Val);
1778 if (Subtarget->hasFullFP16()) {
1779 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1782 Val = DAG.
getNode(ISD::BITCAST, dl,
1787 return DAG.
getNode(ISD::BITCAST, dl, LocVT, Val);
1792SDValue ARMTargetLowering::LowerCallResult(
1796 SDValue ThisVal,
bool isCmseNSCall)
const {
1804 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1805 CCValAssign VA = RVLocs[i];
1809 if (i == 0 && isThisReturn) {
1811 "unexpected return calling convention register assignment");
1829 if (!Subtarget->isLittle())
1831 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1846 if (!Subtarget->isLittle())
1848 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1878 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1889std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1891 bool IsTailCall,
int SPDiff)
const {
1893 MachinePointerInfo DstInfo;
1913 return std::make_pair(DstAddr, DstInfo);
1922ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1935 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1938 int SrcFI = SrcFrameIdxNode->getIndex();
1939 int DstFI = DstFrameIdxNode->getIndex();
1941 "byval passed in non-fixed stack slot");
1963 if (SrcOffset == DstOffset)
1971 RegsToPassVector &RegsToPass,
1978 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1979 unsigned id = Subtarget->isLittle() ? 0 : 1;
1991 MachinePointerInfo DstInfo;
1992 std::tie(DstAddr, DstInfo) =
1993 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2010 SelectionDAG &DAG = CLI.
DAG;
2012 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2013 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2014 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2021 const CallBase *CB = CLI.
CB;
2024 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2026 MachineFunction::CallSiteInfo CSInfo;
2027 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2028 bool isThisReturn =
false;
2029 bool isCmseNSCall =
false;
2030 bool isSibCall =
false;
2031 bool PreferIndirect =
false;
2032 bool GuardWithBTI =
false;
2042 !Subtarget->noBTIAtReturnTwice())
2047 CSInfo = MachineFunction::CallSiteInfo(*CB);
2051 isCmseNSCall =
true;
2054 if (!Subtarget->supportsTailCall())
2070 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2071 count_if(GV->users(), [&BB](
const User *U) {
2072 return isa<Instruction>(U) &&
2073 cast<Instruction>(U)->getParent() == BB;
2080 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2094 "site marked musttail");
2097 unsigned NumBytes = CCInfo.getStackSize();
2106 if (isTailCall && !isSibCall) {
2107 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2108 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2113 assert(StackAlign &&
"data layout string is missing stack alignment");
2114 NumBytes =
alignTo(NumBytes, *StackAlign);
2119 SPDiff = NumReusableBytes - NumBytes;
2123 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2139 RegsToPassVector RegsToPass;
2148 DenseMap<unsigned, SDValue> ByValTemporaries;
2152 for (
const CCValAssign &VA : ArgLocs) {
2154 SDValue Src = OutVals[ArgIdx];
2155 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2157 if (!
Flags.isByVal())
2161 MachinePointerInfo DstInfo;
2162 std::tie(Dst, DstInfo) =
2163 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2164 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2166 if (Copy == NoCopy) {
2171 }
else if (Copy == CopyOnce) {
2175 ByValTemporaries[ArgIdx] = Src;
2177 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2181 int TempFrameIdx = MFI.CreateStackObject(
2182 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2190 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2191 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2193 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2194 ByValTemporaries[ArgIdx] = Temp;
2197 if (!ByValCopyChains.
empty())
2207 bool AfterFormalArgLoads =
false;
2211 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2213 ++i, ++realArgIdx) {
2214 CCValAssign &VA = ArgLocs[i];
2215 SDValue Arg = OutVals[realArgIdx];
2216 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2217 bool isByVal =
Flags.isByVal();
2237 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2239 if (ByValTempChain) {
2244 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2245 if (Outs[
I].
Flags.isByVal())
2253 FrameIndexSDNode *FIN =
2258 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2261 for (
const CCValAssign &VA : ArgLocs) {
2269 if (!IncomingLoad.
empty()) {
2277 AfterFormalArgLoads =
true;
2289 auto ArgVT = Outs[realArgIdx].ArgVT;
2290 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2308 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2309 StackPtr, MemOpChains, isTailCall, SPDiff);
2313 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2314 StackPtr, MemOpChains, isTailCall, SPDiff);
2318 MachinePointerInfo DstInfo;
2319 std::tie(DstAddr, DstInfo) =
2320 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2324 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2325 StackPtr, MemOpChains, isTailCall, SPDiff);
2327 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2328 Outs[0].VT == MVT::i32) {
2330 "unexpected calling convention register assignment");
2332 "unexpected use of 'returned'");
2333 isThisReturn =
true;
2338 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2339 }
else if (isByVal) {
2341 unsigned offset = 0;
2345 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2346 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2349 bool NeedsStackCopy;
2350 if (
auto It = ByValTemporaries.
find(realArgIdx);
2351 It != ByValTemporaries.
end()) {
2352 ByValSrc = It->second;
2353 NeedsStackCopy =
true;
2356 NeedsStackCopy = !isTailCall;
2360 if (CurByValIdx < ByValArgsCount) {
2361 unsigned RegBegin, RegEnd;
2362 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2366 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2370 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2373 RegsToPass.push_back(std::make_pair(j, Load));
2378 offset = RegEnd - RegBegin;
2380 CCInfo.nextInRegsParam();
2385 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2388 MachinePointerInfo DstInfo;
2389 std::tie(Dst, DstInfo) =
2390 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2398 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2399 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2406 MachinePointerInfo DstInfo;
2407 std::tie(DstAddr, DstInfo) =
2408 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2415 if (!MemOpChains.
empty())
2421 for (
const auto &[
Reg,
N] : RegsToPass) {
2429 bool isDirect =
false;
2432 const GlobalValue *GVal =
nullptr;
2434 GVal =
G->getGlobal();
2435 bool isStub = !TM.shouldAssumeDSOLocal(GVal) && Subtarget->isTargetMachO();
2437 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2438 bool isLocalARMFunc =
false;
2441 if (Subtarget->genLongCalls()) {
2443 "long-calls codegen is not position independent!");
2448 if (Subtarget->genExecuteOnly()) {
2449 if (Subtarget->useMovt())
2461 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2467 const char *Sym = S->getSymbol();
2469 if (Subtarget->genExecuteOnly()) {
2470 if (Subtarget->useMovt())
2482 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2489 if (!PreferIndirect) {
2494 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2496 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2497 assert(Subtarget->isTargetMachO() &&
"WrapperPIC use on non-MachO?");
2499 ARMISD::WrapperPIC, dl, PtrVt,
2506 }
else if (Subtarget->isTargetCOFF()) {
2507 assert(Subtarget->isTargetWindows() &&
2508 "Windows is the only supported COFF target");
2512 else if (!TM.shouldAssumeDSOLocal(GVal))
2519 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2528 const char *Sym = S->getSymbol();
2529 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2531 ARMConstantPoolValue *CPV =
2533 ARMPCLabelIndex, 4);
2535 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2540 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2547 assert(!isARMFunc && !isDirect &&
2548 "Cannot handle call to ARM function or direct call");
2552 "call to non-secure function would require "
2553 "passing arguments on stack",
2559 "call to non-secure function would return value through pointer",
2566 if (Subtarget->isThumb()) {
2568 CallOpc = ARMISD::t2CALL_BTI;
2569 else if (isCmseNSCall)
2570 CallOpc = ARMISD::tSECALL;
2571 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2572 CallOpc = ARMISD::CALL_NOLINK;
2574 CallOpc = ARMISD::CALL;
2576 if (!isDirect && !Subtarget->hasV5TOps())
2577 CallOpc = ARMISD::CALL_NOLINK;
2578 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2580 !Subtarget->hasMinSize())
2582 CallOpc = ARMISD::CALL_NOLINK;
2584 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2591 if (isTailCall && !isSibCall) {
2596 std::vector<SDValue>
Ops;
2597 Ops.push_back(Chain);
2598 Ops.push_back(Callee);
2606 for (
const auto &[
Reg,
N] : RegsToPass)
2610 const uint32_t *
Mask;
2611 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2619 isThisReturn =
false;
2625 assert(Mask &&
"Missing call preserved mask for calling convention");
2629 Ops.push_back(InGlue);
2642 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2653 uint64_t CalleePopBytes =
2656 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2662 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2663 InVals, isThisReturn,
2664 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2671void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2672 Align Alignment)
const {
2674 Alignment = std::max(Alignment,
Align(4));
2680 unsigned AlignInRegs = Alignment.
value() / 4;
2681 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2682 for (
unsigned i = 0; i < Waste; ++i)
2688 unsigned Excess = 4 * (ARM::R4 -
Reg);
2695 if (NSAAOffset != 0 &&
Size > Excess) {
2707 unsigned ByValRegBegin =
Reg;
2708 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2712 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2718 Size = std::max<int>(
Size - Excess, 0);
2726bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2732 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2733 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2734 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2735 const SelectionDAG &DAG = CLI.
DAG;
2740 assert(Subtarget->supportsTailCall());
2753 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2755 if (!(Subtarget->isThumb1Only() ||
2756 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2757 AddressRegisters.
insert(ARM::R12);
2758 for (
const CCValAssign &AL : ArgLocs)
2760 AddressRegisters.
erase(
AL.getLocReg());
2761 if (AddressRegisters.
empty()) {
2762 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2781 <<
" (guaranteed tail-call CC)\n");
2782 return CalleeCC == CallerCC;
2787 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2789 if (isCalleeStructRet != isCallerStructRet) {
2802 const GlobalValue *GV =
G->getGlobal();
2805 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2806 TT.isOSBinFormatMachO())) {
2815 getEffectiveCallingConv(CalleeCC, isVarArg),
2816 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
2823 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2824 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2825 if (CalleeCC != CallerCC) {
2826 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2827 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2836 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2846 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2865 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2874 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2887 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2890 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2894 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2899 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2921 bool isLittleEndian = Subtarget->isLittle();
2924 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2933 "secure entry function would return value through pointer",
2938 for (
unsigned i = 0, realRVLocIdx = 0;
2940 ++i, ++realRVLocIdx) {
2941 CCValAssign &VA = RVLocs[i];
2944 SDValue Arg = OutVals[realRVLocIdx];
2945 bool ReturnF16 =
false;
2947 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
2980 auto RetVT = Outs[realRVLocIdx].ArgVT;
3002 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3006 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3012 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3024 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3026 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3031 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3041 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3067 !Subtarget->isMClass()) {
3068 if (Subtarget->isThumb1Only())
3075 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3078bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3079 if (
N->getNumValues() != 1)
3081 if (!
N->hasNUsesOfValue(1, 0))
3085 SDNode *
Copy = *
N->user_begin();
3089 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3091 TCChain =
Copy->getOperand(0);
3092 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3093 SDNode *VMov =
Copy;
3095 SmallPtrSet<SDNode*, 2>
Copies;
3096 for (SDNode *U : VMov->
users()) {
3104 for (SDNode *U : VMov->
users()) {
3105 SDValue UseChain =
U->getOperand(0);
3113 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3119 }
else if (
Copy->getOpcode() == ISD::BITCAST) {
3121 if (!
Copy->hasOneUse())
3128 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3130 TCChain =
Copy->getOperand(0);
3135 bool HasRet =
false;
3136 for (
const SDNode *U :
Copy->users()) {
3137 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3138 U->getOpcode() != ARMISD::INTRET_GLUE)
3150bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3151 if (!Subtarget->supportsTailCall())
3168 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3184 EVT PtrVT =
Op.getValueType();
3194 if (Subtarget->genExecuteOnly()) {
3196 auto *
T =
CP->getType();
3197 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3199 auto GV =
new GlobalVariable(
3207 return LowerGlobalAddress(GA, DAG);
3212 Align CPAlign =
CP->getAlign();
3213 if (Subtarget->isThumb1Only())
3214 CPAlign = std::max(CPAlign,
Align(4));
3215 if (
CP->isMachineConstantPoolEntry())
3220 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3227 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3236 unsigned ARMPCLabelIndex = 0;
3242 if (!IsPositionIndependent) {
3245 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3252 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3256 if (!IsPositionIndependent)
3259 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3287ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3289 assert(Subtarget->isTargetDarwin() &&
3290 "This function expects a Darwin target");
3295 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3301 MVT::i32,
DL, Chain, DescAddr,
3316 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3325 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3331ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3333 assert(Subtarget->isTargetWindows() &&
"Windows specific TLS lowering");
3357 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3365 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3366 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3372 MachinePointerInfo());
3379 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3392 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3394 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3396 ARMConstantPoolValue *CPV =
3407 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3414 TargetLowering::CallLoweringInfo CLI(DAG);
3419 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3420 return CallResult.first;
3429 const GlobalValue *GV = GA->
getGlobal();
3435 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3439 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3442 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3443 ARMConstantPoolValue *CPV =
3450 PtrVT, dl, Chain,
Offset,
3458 PtrVT, dl, Chain,
Offset,
3463 ARMConstantPoolValue *CPV =
3468 PtrVT, dl, Chain,
Offset,
3483 if (Subtarget->isTargetDarwin())
3484 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3486 if (Subtarget->isTargetWindows())
3487 return LowerGlobalTLSAddressWindows(
Op, DAG);
3490 assert(Subtarget->isTargetELF() &&
"Only ELF implemented here");
3496 return LowerToTLSGeneralDynamicModel(GA, DAG);
3499 return LowerToTLSExecModels(GA, DAG, model);
3508 while (!Worklist.
empty()) {
3516 if (!
I ||
I->getParent()->getParent() !=
F)
3545 if (!GVar || !GVar->hasInitializer() ||
3546 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3547 !GVar->hasLocalLinkage())
3552 auto *
Init = GVar->getInitializer();
3554 Init->needsDynamicRelocation())
3566 unsigned RequiredPadding = 4 - (
Size % 4);
3567 bool PaddingPossible =
3568 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3573 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3597 if (RequiredPadding != 4) {
3602 while (RequiredPadding--)
3614 ++NumConstpoolPromoted;
3615 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3620 if (!(GV = GA->getAliaseeObject()))
3623 return V->isConstant();
3632 return LowerGlobalAddressWindows(
Op, DAG);
3634 return LowerGlobalAddressELF(
Op, DAG);
3636 return LowerGlobalAddressDarwin(
Op, DAG);
3648 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3661 }
else if (Subtarget->isROPI() && IsRO) {
3666 }
else if (Subtarget->isRWPI() && !IsRO) {
3669 if (Subtarget->useMovt()) {
3672 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3674 ARMConstantPoolValue *CPV =
3677 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3691 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3692 if (Subtarget->useMovt())
3696 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3700 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3709 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3710 "ROPI/RWPI not currently supported for Darwin");
3715 if (Subtarget->useMovt())
3726 if (Subtarget->isGVIndirectSymbol(GV))
3734 assert(Subtarget->isTargetWindows() &&
"non-Windows COFF is not supported");
3735 assert(Subtarget->useMovt() &&
3736 "Windows on ARM expects to use movw/movt");
3737 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3738 "ROPI/RWPI not currently supported for Windows");
3745 else if (!TM.shouldAssumeDSOLocal(GV))
3768 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3769 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3770 Op.getOperand(1), Val);
3776 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3783 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3787SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3790 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3794 case Intrinsic::arm_gnu_eabi_mcount: {
3800 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3801 const uint32_t *
Mask =
3803 assert(Mask &&
"Missing call preserved mask for calling convention");
3808 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3812 if (Subtarget->isThumb())
3815 ARM::tBL_PUSHLR, dl, ResultTys,
3816 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3817 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3821 {ReturnAddress, Callee, RegisterMask, Chain}),
3830 unsigned IntNo =
Op.getConstantOperandVal(0);
3834 case Intrinsic::thread_pointer: {
3836 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3838 case Intrinsic::arm_cls: {
3839 const SDValue &Operand =
Op.getOperand(1);
3840 const EVT VTy =
Op.getValueType();
3851 case Intrinsic::arm_cls64: {
3854 const SDValue &Operand =
Op.getOperand(1);
3855 const EVT VTy =
Op.getValueType();
3878 case Intrinsic::eh_sjlj_lsda: {
3880 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3885 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3886 ARMConstantPoolValue *CPV =
3890 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3895 if (IsPositionIndependent) {
3897 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3901 case Intrinsic::arm_neon_vabs:
3904 case Intrinsic::arm_neon_vabds:
3905 if (
Op.getValueType().isInteger())
3907 Op.getOperand(1),
Op.getOperand(2));
3909 case Intrinsic::arm_neon_vabdu:
3911 Op.getOperand(1),
Op.getOperand(2));
3912 case Intrinsic::arm_neon_vmulls:
3913 case Intrinsic::arm_neon_vmullu: {
3914 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3915 ? ARMISD::VMULLs : ARMISD::VMULLu;
3916 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3917 Op.getOperand(1),
Op.getOperand(2));
3919 case Intrinsic::arm_neon_vminnm:
3920 case Intrinsic::arm_neon_vmaxnm: {
3921 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3922 ? ISD::FMINNUM : ISD::FMAXNUM;
3923 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3924 Op.getOperand(1),
Op.getOperand(2));
3926 case Intrinsic::arm_neon_vminu:
3927 case Intrinsic::arm_neon_vmaxu: {
3928 if (
Op.getValueType().isFloatingPoint())
3930 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3932 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3933 Op.getOperand(1),
Op.getOperand(2));
3935 case Intrinsic::arm_neon_vmins:
3936 case Intrinsic::arm_neon_vmaxs: {
3938 if (!
Op.getValueType().isFloatingPoint()) {
3939 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3941 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3942 Op.getOperand(1),
Op.getOperand(2));
3944 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3945 ? ISD::FMINIMUM : ISD::FMAXIMUM;
3946 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3947 Op.getOperand(1),
Op.getOperand(2));
3949 case Intrinsic::arm_neon_vtbl1:
3950 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
3951 Op.getOperand(1),
Op.getOperand(2));
3952 case Intrinsic::arm_neon_vtbl2:
3953 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
3954 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3955 case Intrinsic::arm_mve_pred_i2v:
3956 case Intrinsic::arm_mve_pred_v2i:
3957 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
3959 case Intrinsic::arm_mve_vreinterpretq:
3960 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
3962 case Intrinsic::arm_mve_lsll:
3963 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
3964 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3965 case Intrinsic::arm_mve_asrl:
3966 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
3967 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3978 if (!Subtarget->hasDataBarrier()) {
3982 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
3983 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
3984 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
3994 }
else if (Subtarget->preferISHSTBarriers() &&
4003 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4011 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4013 return Op.getOperand(0);
4016 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4018 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4020 return Op.getOperand(0);
4022 unsigned isData =
Op.getConstantOperandVal(4);
4023 if (Subtarget->isThumb()) {
4025 isRead = ~isRead & 1;
4026 isData = ~isData & 1;
4029 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4044 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4052 const SDLoc &dl)
const {
4054 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4056 const TargetRegisterClass *RC;
4058 RC = &ARM::tGPRRegClass;
4060 RC = &ARM::GPRRegClass;
4074 MVT::i32, dl, Root, FIN,
4080 if (!Subtarget->isLittle())
4082 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4095 const Value *OrigArg,
4096 unsigned InRegsParamRecordIdx,
4097 int ArgOffset,
unsigned ArgSize)
const {
4111 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4112 unsigned RBegin, REnd;
4117 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4122 ArgOffset = -4 * (ARM::R4 - RBegin);
4129 const TargetRegisterClass *RC =
4132 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4136 MachinePointerInfo(OrigArg, 4 * i));
4141 if (!MemOps.
empty())
4150 unsigned TotalArgRegsSaveSize,
4151 bool ForceMutable)
const {
4153 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4162 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4166bool ARMTargetLowering::splitValueIntoRegisterParts(
4168 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4170 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4175 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
4182SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4184 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4185 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4192 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
4198SDValue ARMTargetLowering::LowerFormalArguments(
4205 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4214 unsigned CurArgIdx = 0;
4226 unsigned ArgRegBegin = ARM::R4;
4227 for (
const CCValAssign &VA : ArgLocs) {
4233 if (!
Flags.isByVal())
4237 unsigned RBegin, REnd;
4239 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4245 int lastInsIndex = -1;
4249 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4252 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4256 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4257 CCValAssign &VA = ArgLocs[i];
4258 if (Ins[VA.
getValNo()].isOrigArg()) {
4259 std::advance(CurOrigArg,
4260 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4261 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4272 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4279 MVT::f64, dl, Chain, FIN,
4282 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4290 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4292 const TargetRegisterClass *RC;
4294 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4295 RC = &ARM::HPRRegClass;
4296 else if (RegVT == MVT::f32)
4297 RC = &ARM::SPRRegClass;
4298 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4299 RegVT == MVT::v4bf16)
4300 RC = &ARM::DPRRegClass;
4301 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4302 RegVT == MVT::v8bf16)
4303 RC = &ARM::QPRRegClass;
4304 else if (RegVT == MVT::i32)
4306 : &ARM::GPRRegClass;
4343 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4352 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4358 if (index != lastInsIndex)
4360 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4366 if (
Flags.isByVal()) {
4367 assert(Ins[index].isOrigArg() &&
4368 "Byval arguments cannot be implicit");
4372 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4406 lastInsIndex = index;
4413 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4414 TotalArgRegsSaveSize);
4418 "secure entry function must not be variadic", dl.
getDebugLoc()));
4428 assert(StackAlign &&
"data layout string is missing stack alignment");
4429 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4438 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4447 return CFP->getValueAPF().isPosZero();
4450 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4451 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4454 return CFP->getValueAPF().isPosZero();
4456 }
else if (
Op->getOpcode() == ISD::BITCAST &&
4457 Op->getValueType(0) == MVT::f64) {
4461 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4472 const SDLoc &dl)
const {
4474 unsigned C = RHSC->getZExtValue();
4538 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4542 unsigned Mask =
LHS.getConstantOperandVal(1);
4544 uint64_t RHSV = RHSC->getZExtValue();
4545 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4547 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4561 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4564 LHS.getConstantOperandVal(1) < 31) {
4565 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4590 unsigned CompareType;
4593 CompareType = ARMISD::CMP;
4598 CompareType = ARMISD::CMPZ;
4608 bool Signaling)
const {
4609 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4615 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4624std::pair<SDValue, SDValue>
4627 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4639 switch (
Op.getOpcode()) {
4691 return std::make_pair(
Value, OverflowCmp);
4702 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4707 EVT VT =
Op.getValueType();
4710 DAG.
getNode(ARMISD::CMOV, dl, VT, TVal, FVal, ARMcc, OverflowCmp);
4712 SDVTList VTs = DAG.
getVTList(
Op.getValueType(), MVT::i32);
4750 EVT VT =
Op.getValueType();
4751 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4754 switch (
Op.getOpcode()) {
4779 EVT VT =
Op.getValueType();
4780 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4790 switch (
Op->getOpcode()) {
4792 NewOpcode = ARMISD::UQADD8b;
4795 NewOpcode = ARMISD::QADD8b;
4798 NewOpcode = ARMISD::UQSUB8b;
4801 NewOpcode = ARMISD::QSUB8b;
4806 switch (
Op->getOpcode()) {
4808 NewOpcode = ARMISD::UQADD16b;
4811 NewOpcode = ARMISD::QADD16b;
4814 NewOpcode = ARMISD::UQSUB16b;
4817 NewOpcode = ARMISD::QSUB16b;
4825 DAG.
getNode(NewOpcode, dl, MVT::i32,
4836 unsigned Opc =
Cond.getOpcode();
4838 if (
Cond.getResNo() == 1 &&
4846 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4847 EVT VT =
Op.getValueType();
4849 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4857 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4858 const ConstantSDNode *CMOVTrue =
4860 const ConstantSDNode *CMOVFalse =
4863 if (CMOVTrue && CMOVFalse) {
4869 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
4871 False = SelectFalse;
4872 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
4878 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
4879 Cond.getOperand(3), DAG);
4894 bool &swpCmpOps,
bool &swpVselOps) {
4922 swpCmpOps = !swpCmpOps;
4923 swpVselOps = !swpVselOps;
4946 if (!Subtarget->hasFP64() && VT == MVT::f64) {
4948 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
4950 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
4964 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
4985 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
4987 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5008 EVT VT =
Op.getValueType();
5030 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5043 int64_t PosVal = std::max(Val1, Val2);
5044 int64_t NegVal = std::min(Val1, Val2);
5056 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5059 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5091 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5096 if (*K != KTmp || V != VTmp)
5107bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5109 return !Subtarget->hasVFP2Base();
5111 return !Subtarget->hasFP64();
5113 return !Subtarget->hasFullFP16();
5118 EVT VT =
Op.getValueType();
5122 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5134 if (VT == MVT::i32 &&
5154 if (
Op.getValueType().isInteger()) {
5162 LHS.getValueType() ==
RHS.getValueType()) {
5163 EVT VT =
LHS.getValueType();
5169 Shift = DAG.
getNOT(dl, Shift, VT);
5175 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5176 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5179 unsigned Opcode = 0;
5181 if (TVal == ~FVal) {
5182 Opcode = ARMISD::CSINV;
5183 }
else if (TVal == ~FVal + 1) {
5184 Opcode = ARMISD::CSNEG;
5185 }
else if (TVal + 1 == FVal) {
5186 Opcode = ARMISD::CSINC;
5187 }
else if (TVal == FVal + 1) {
5188 Opcode = ARMISD::CSINC;
5197 if (Opcode != ARMISD::CSINC &&
5207 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5218 EVT VT =
TrueVal.getValueType();
5219 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5223 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5228 if (!
RHS.getNode()) {
5234 if (
LHS.getValueType() == MVT::i32) {
5245 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5246 TrueVal.getValueType() == MVT::f32 ||
5247 TrueVal.getValueType() == MVT::f64)) {
5261 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5271 if (Subtarget->hasFPARMv8Base() &&
5273 (
TrueVal.getValueType() == MVT::f16 ||
5274 TrueVal.getValueType() == MVT::f32 ||
5275 TrueVal.getValueType() == MVT::f64)) {
5276 bool swpCmpOps =
false;
5277 bool swpVselOps =
false;
5291 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5294 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5304 if (!
N->hasOneUse())
5307 if (!
N->getNumValues())
5309 EVT VT =
Op.getValueType();
5310 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5327 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5328 Ld->getPointerInfo(), Ld->getAlign(),
5329 Ld->getMemOperand()->getFlags());
5345 SDValue Ptr = Ld->getBasePtr();
5347 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5348 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5353 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5354 Ld->getPointerInfo().getWithOffset(4),
5356 Ld->getMemOperand()->getFlags());
5374 bool LHSSeenZero =
false;
5376 bool RHSSeenZero =
false;
5378 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5389 if (
LHS.getValueType() == MVT::f32) {
5395 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5407 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5408 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5423 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5435 unsigned Opc =
Cond.getOpcode();
5437 !Subtarget->isThumb1Only();
5438 if (
Cond.getResNo() == 1 &&
5448 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5454 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5456 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5471 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5476 if (!
RHS.getNode()) {
5484 unsigned Opc =
LHS.getOpcode();
5486 !Subtarget->isThumb1Only();
5498 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5505 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5508 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5512 if (
LHS.getValueType() == MVT::i32) {
5515 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5518 SDNodeFlags
Flags =
Op->getFlags();
5519 if (
Flags.hasNoNaNs() &&
5524 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5538 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5552 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5555 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5560 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5561 Addr,
Op.getOperand(2), JTI);
5565 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5569 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5572 DAG.
getLoad(PTy, dl, Chain, Addr,
5575 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5580 EVT VT =
Op.getValueType();
5583 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5584 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5592 const EVT OpTy =
Op.getOperand(0).getValueType();
5593 if (OpTy == MVT::v4f32)
5595 else if (OpTy == MVT::v4f16 && HasFullFP16)
5597 else if (OpTy == MVT::v8f16 && HasFullFP16)
5602 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5605 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5610 EVT VT =
Op.getValueType();
5614 bool IsStrict =
Op->isStrictFPOpcode();
5615 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5617 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5630 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5631 CallOptions, Loc, Chain);
5641 Loc,
Op.getValueType(), SrcVal);
5650 EVT VT =
Op.getValueType();
5652 EVT FromVT =
Op.getOperand(0).getValueType();
5654 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5656 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5657 Subtarget->hasFP64())
5659 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5660 Subtarget->hasFullFP16())
5662 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5663 Subtarget->hasMVEFloatOps())
5665 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5666 Subtarget->hasMVEFloatOps())
5669 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5686 EVT VT =
Op.getValueType();
5689 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5695 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5696 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5697 "Invalid type for custom lowering!");
5702 if (VT == MVT::v4f32)
5703 DestVecType = MVT::v4i32;
5704 else if (VT == MVT::v4f16 && HasFullFP16)
5705 DestVecType = MVT::v4i16;
5706 else if (VT == MVT::v8f16 && HasFullFP16)
5707 DestVecType = MVT::v8i16;
5713 switch (
Op.getOpcode()) {
5725 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5730 EVT VT =
Op.getValueType();
5733 if (isUnsupportedFloatingType(VT)) {
5743 CallOptions, SDLoc(
Op)).first;
5754 EVT VT =
Op.getValueType();
5756 bool InGPR = Tmp0.
getOpcode() == ISD::BITCAST ||
5758 bool UseNEON = !InGPR && Subtarget->hasNEON();
5765 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5768 DAG.
getNode(ISD::BITCAST, dl, OpVT, Mask),
5772 if (SrcVT == MVT::f32) {
5775 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5776 DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1),
5778 }
else if (VT == MVT::f32)
5779 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5780 DAG.
getNode(ISD::BITCAST, dl, MVT::v1i64, Tmp1),
5782 Tmp0 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp0);
5783 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, OpVT, Tmp1);
5794 if (VT == MVT::f32) {
5795 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::v2f32, Res);
5799 Res = DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Res);
5806 if (SrcVT == MVT::f64)
5809 Tmp1 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp1);
5815 if (VT == MVT::f32) {
5817 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
5818 return DAG.
getNode(ISD::BITCAST, dl, MVT::f32,
5828 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5836 EVT VT =
Op.getValueType();
5838 unsigned Depth =
Op.getConstantOperandVal(0);
5840 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5844 MachinePointerInfo());
5853 const ARMBaseRegisterInfo &ARI =
5854 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
5859 EVT VT =
Op.getValueType();
5861 unsigned Depth =
Op.getConstantOperandVal(0);
5866 MachinePointerInfo());
5874 return StringSwitch<Register>(
RegName)
5875 .Case(
"sp", ARM::SP)
5886 assert(
N->getValueType(0) == MVT::i64
5887 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
5890 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
5930 const APInt &APIntIndex = Index->getAPIntValue();
5932 NewIndex *= APIntIndex;
5944 SDValue BitCast = DAG.
getNode(ISD::BITCAST, dl, VecVT, ExtractSrc);
5961 EVT SrcVT =
Op.getValueType();
5962 EVT DstVT =
N->getValueType(0);
5964 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
5965 (DstVT == MVT::f16 || DstVT == MVT::bf16))
5966 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
5969 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
5970 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
5971 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
5978 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
5989 return DAG.
getNode(ISD::BITCAST, dl, DstVT,
5990 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
5998 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6000 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6002 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6022 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6023 return DAG.
getNode(ISD::BITCAST, dl, VT, Vmov);
6031 EVT VT =
Op.getValueType();
6053 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6063 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6074 EVT VT =
Op.getValueType();
6095 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6116 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6168 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6196 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6226 EVT VT =
N->getValueType(0);
6227 if (VT.
isVector() && ST->hasNEON()) {
6236 if (ElemTy == MVT::i8) {
6244 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6247 unsigned NumBits = ElemTy.getSizeInBits();
6249 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6259 if (ElemTy == MVT::i64) {
6272 if (!ST->hasV6T2Ops())
6281 EVT VT =
N->getValueType(0);
6284 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6285 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6286 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6287 "Unexpected type for custom ctpop lowering");
6295 unsigned EltSize = 8;
6317 while (
Op.getOpcode() == ISD::BITCAST)
6318 Op =
Op.getOperand(0);
6320 APInt SplatBits, SplatUndef;
6321 unsigned SplatBitSize;
6324 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6326 SplatBitSize > ElementBits)
6337 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6341 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6352 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6357 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6358 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6367 EVT VT =
N->getValueType(0);
6382 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6384 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6389 "unexpected vector shift opcode");
6391 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6392 unsigned VShiftOpc =
6393 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6394 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6400 EVT ShiftVT =
N->getOperand(1).getValueType();
6403 unsigned VShiftOpc =
6404 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6405 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6410 EVT VT =
N->getValueType(0);
6419 "Unknown shift to lower!");
6421 unsigned ShOpc =
N->getOpcode();
6422 if (ST->hasMVEIntegerOps()) {
6424 unsigned ShPartsOpc = ARMISD::LSLL;
6445 ShPartsOpc = ARMISD::LSRL;
6447 ShPartsOpc = ARMISD::ASRL;
6452 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6466 if (ST->isThumb1Only())
6471 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6475 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6479 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6487 bool Invert =
false;
6494 EVT VT =
Op.getValueType();
6502 assert(ST->hasMVEIntegerOps() &&
6503 "No hardware support for integer vector comparison!");
6505 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6526 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6528 Merged = DAG.
getNode(ISD::BITCAST, dl, CmpVT, Merged);
6530 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6540 switch (SetCCOpcode) {
6544 if (ST->hasMVEFloatOps()) {
6547 Invert =
true; [[fallthrough]];
6552 case ISD::SETLT: Swap =
true; [[fallthrough]];
6556 case ISD::SETLE: Swap =
true; [[fallthrough]];
6572 Result = DAG.
getNOT(dl, Result, VT);
6575 case ISD::SETUO: Invert =
true; [[fallthrough]];
6584 Result = DAG.
getNOT(dl, Result, VT);
6590 switch (SetCCOpcode) {
6593 if (ST->hasMVEIntegerOps()) {
6596 Invert =
true; [[fallthrough]];
6599 case ISD::SETLT: Swap =
true; [[fallthrough]];
6601 case ISD::SETLE: Swap =
true; [[fallthrough]];
6618 if (AndOp.getNode() && AndOp.getOpcode() == ISD::BITCAST)
6621 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6622 Op0 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(0));
6623 Op1 = DAG.
getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(1));
6626 Result = DAG.
getNOT(dl, Result, VT);
6651 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6654 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6660 Result = DAG.
getNOT(dl, Result, VT);
6672 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6688 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6699 unsigned OpCmode, Imm;
6710 switch (SplatBitSize) {
6715 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6718 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6723 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6724 if ((SplatBits & ~0xff) == 0) {
6730 if ((SplatBits & ~0xff00) == 0) {
6733 Imm = SplatBits >> 8;
6743 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6744 if ((SplatBits & ~0xff) == 0) {
6750 if ((SplatBits & ~0xff00) == 0) {
6753 Imm = SplatBits >> 8;
6756 if ((SplatBits & ~0xff0000) == 0) {
6759 Imm = SplatBits >> 16;
6762 if ((SplatBits & ~0xff000000) == 0) {
6765 Imm = SplatBits >> 24;
6772 if ((SplatBits & ~0xffff) == 0 &&
6773 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6776 Imm = SplatBits >> 8;
6784 if ((SplatBits & ~0xffffff) == 0 &&
6785 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6788 Imm = SplatBits >> 16;
6804 unsigned ImmMask = 1;
6806 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6807 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6809 }
else if ((SplatBits & BitMask) != 0) {
6818 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6832 EVT VT =
Op.getValueType();
6833 bool IsDouble = (VT == MVT::f64);
6839 if (
ST->genExecuteOnly()) {
6841 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6842 "Unexpected architecture");
6860 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
6865 if (!
ST->hasVFP3Base())
6870 if (IsDouble && !Subtarget->hasFP64())
6877 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
6895 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
6904 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
6915 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
6932 return DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, VecConstant);
6958 unsigned ExpectedElt = Imm;
6959 for (
unsigned i = 1; i < NumElts; ++i) {
6963 if (ExpectedElt == NumElts)
6966 if (M[i] < 0)
continue;
6967 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
6975 bool &ReverseVEXT,
unsigned &Imm) {
6977 ReverseVEXT =
false;
6988 unsigned ExpectedElt = Imm;
6989 for (
unsigned i = 1; i < NumElts; ++i) {
6993 if (ExpectedElt == NumElts * 2) {
6998 if (M[i] < 0)
continue;
6999 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7014 return VT == MVT::v8i8 && M.size() == 8;
7019 if (Mask.size() == Elements * 2)
7020 return Index / Elements;
7021 return Mask[Index] == 0 ? 0 : 1;
7051 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7059 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7061 for (
unsigned j = 0; j < NumElts; j += 2) {
7062 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7063 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7068 if (M.size() == NumElts*2)
7083 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7086 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7088 for (
unsigned j = 0; j < NumElts; j += 2) {
7089 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7090 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7095 if (M.size() == NumElts*2)
7115 if (M.size() != NumElts && M.size() != NumElts*2)
7118 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7120 for (
unsigned j = 0; j < NumElts; ++j) {
7121 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7126 if (M.size() == NumElts*2)
7145 if (M.size() != NumElts && M.size() != NumElts*2)
7148 unsigned Half = NumElts / 2;
7149 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7151 for (
unsigned j = 0; j < NumElts; j += Half) {
7152 unsigned Idx = WhichResult;
7153 for (
unsigned k = 0; k < Half; ++k) {
7154 int MIdx = M[i + j + k];
7155 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7162 if (M.size() == NumElts*2)
7186 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7189 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7191 unsigned Idx = WhichResult * NumElts / 2;
7192 for (
unsigned j = 0; j < NumElts; j += 2) {
7193 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7194 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7200 if (M.size() == NumElts*2)
7219 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7222 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7224 unsigned Idx = WhichResult * NumElts / 2;
7225 for (
unsigned j = 0; j < NumElts; j += 2) {
7226 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7227 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7233 if (M.size() == NumElts*2)
7246 unsigned &WhichResult,
7249 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7250 return ARMISD::VTRN;
7251 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7252 return ARMISD::VUZP;
7253 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7254 return ARMISD::VZIP;
7258 return ARMISD::VTRN;
7260 return ARMISD::VUZP;
7262 return ARMISD::VZIP;
7271 if (NumElts != M.size())
7275 for (
unsigned i = 0; i != NumElts; ++i)
7276 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7285 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7293 int Ofs = Top ? 1 : 0;
7294 int Upper = SingleSource ? 0 : NumElts;
7295 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7296 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7298 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7307 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7316 unsigned Offset = Top ? 0 : 1;
7317 unsigned N = SingleSource ? 0 : NumElts;
7318 for (
unsigned i = 0; i < NumElts; i += 2) {
7319 if (M[i] >= 0 && M[i] != (
int)i)
7321 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7330 if (NumElts != M.size())
7338 unsigned Off0 = rev ? NumElts / 2 : 0;
7339 unsigned Off1 = rev ? 0 : NumElts / 2;
7340 for (
unsigned i = 0; i < NumElts; i += 2) {
7341 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7343 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7359 if (!ST->hasMVEFloatOps())
7364 if (VT != MVT::v8f16)
7385 for (
unsigned i = 1; i < 4; i++) {
7400 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7412 if (!ST->hasMVEFloatOps())
7417 if (VT != MVT::v4f32)
7433 for (
unsigned i = 1; i < 4; i++) {
7435 return Trunc.
getOpcode() == ISD::FP_EXTEND &&
7444 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7456 Val =
N->getAsZExtVal();
7458 if (ST->isThumb1Only()) {
7459 if (Val <= 255 || ~Val <= 255)
7471 EVT VT =
Op.getValueType();
7473 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7477 unsigned BitsPerBool;
7481 }
else if (NumElts == 4) {
7484 }
else if (NumElts == 8) {
7487 }
else if (NumElts == 16) {
7498 return U.get().isUndef() || U.get() == FirstOp;
7502 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7506 unsigned Bits32 = 0;
7507 for (
unsigned i = 0; i < NumElts; ++i) {
7511 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7513 Bits32 |= BoolMask << (i * BitsPerBool);
7519 for (
unsigned i = 0; i < NumElts; ++i) {
7532 if (!ST->hasMVEIntegerOps())
7536 EVT VT =
Op.getValueType();
7546 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7550 for (
unsigned I = 2;
I < NumElts;
I++) {
7566 switch (
N->getOpcode()) {
7577 return N->getOperand(1).getNode() ==
Op;
7579 switch (
N->getConstantOperandVal(0)) {
7580 case Intrinsic::arm_mve_add_predicated:
7581 case Intrinsic::arm_mve_mul_predicated:
7582 case Intrinsic::arm_mve_qadd_predicated:
7583 case Intrinsic::arm_mve_vhadd:
7584 case Intrinsic::arm_mve_hadd_predicated:
7585 case Intrinsic::arm_mve_vqdmulh:
7586 case Intrinsic::arm_mve_qdmulh_predicated:
7587 case Intrinsic::arm_mve_vqrdmulh:
7588 case Intrinsic::arm_mve_qrdmulh_predicated:
7589 case Intrinsic::arm_mve_vqdmull:
7590 case Intrinsic::arm_mve_vqdmull_predicated:
7592 case Intrinsic::arm_mve_sub_predicated:
7593 case Intrinsic::arm_mve_qsub_predicated:
7594 case Intrinsic::arm_mve_vhsub:
7595 case Intrinsic::arm_mve_hsub_predicated:
7596 return N->getOperand(2).getNode() ==
Op;
7611 EVT VT =
Op.getValueType();
7619 APInt SplatBits, SplatUndef;
7620 unsigned SplatBitSize;
7622 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7629 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7631 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7632 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7633 : SplatBitSize == 16 ? MVT::v8i16
7637 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7640 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7641 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7646 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7650 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7654 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7656 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7660 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7664 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7668 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7674 if (
ST->hasMVEIntegerOps() &&
7675 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7676 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7677 : SplatBitSize == 16 ? MVT::v8i16
7681 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7694 bool isOnlyLowElement =
true;
7695 bool usesOnlyOneValue =
true;
7696 bool hasDominantValue =
false;
7701 DenseMap<SDValue, unsigned> ValueCounts;
7703 for (
unsigned i = 0; i < NumElts; ++i) {
7708 isOnlyLowElement =
false;
7712 unsigned &
Count = ValueCounts[
V];
7715 if (++
Count > (NumElts / 2)) {
7716 hasDominantValue =
true;
7720 if (ValueCounts.
size() != 1)
7721 usesOnlyOneValue =
false;
7722 if (!
Value.getNode() && !ValueCounts.
empty())
7725 if (ValueCounts.
empty())
7737 if (hasDominantValue && EltSize <= 32) {
7746 ConstantSDNode *constIndex;
7753 if (VT !=
Value->getOperand(0).getValueType()) {
7756 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7761 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7766 if (!usesOnlyOneValue) {
7769 for (
unsigned I = 0;
I < NumElts; ++
I) {
7774 Ops.push_back(
Op.getOperand(
I));
7784 assert(FVT == MVT::f32 || FVT == MVT::f16);
7785 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7786 for (
unsigned i = 0; i < NumElts; ++i)
7787 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, IVT,
7791 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7793 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
7795 if (usesOnlyOneValue) {
7798 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7822 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7842 if (EltSize >= 32) {
7848 for (
unsigned i = 0; i < NumElts; ++i)
7849 Ops.push_back(DAG.
getNode(ISD::BITCAST, dl, EltVT,
Op.getOperand(i)));
7851 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
7862 for (
unsigned i = 0 ; i < NumElts; ++i) {
7881 EVT VT =
Op.getValueType();
7884 struct ShuffleSourceInfo {
7886 unsigned MinElt = std::numeric_limits<unsigned>::max();
7887 unsigned MaxElt = 0;
7897 int WindowScale = 1;
7899 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7907 for (
unsigned i = 0; i < NumElts; ++i) {
7922 SDValue SourceVec =
V.getOperand(0);
7924 if (Source == Sources.
end())
7928 unsigned EltNo =
V.getConstantOperandVal(1);
7935 if (Sources.
size() > 2)
7941 for (
auto &Source : Sources) {
7942 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
7943 if (SrcEltTy.
bitsLT(SmallestEltTy))
7944 SmallestEltTy = SrcEltTy;
7946 unsigned ResMultiplier =
7954 for (
auto &Src : Sources) {
7955 EVT SrcVT = Src.ShuffleVec.getValueType();
7959 if (SrcVTSize == VTSize)
7968 if (SrcVTSize < VTSize) {
7969 if (2 * SrcVTSize != VTSize)
7975 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
7979 if (SrcVTSize != 2 * VTSize)
7982 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
7987 if (Src.MinElt >= NumSrcElts) {
7992 Src.WindowBase = -NumSrcElts;
7993 }
else if (Src.MaxElt < NumSrcElts) {
8007 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8010 Src.WindowBase = -Src.MinElt;
8017 for (
auto &Src : Sources) {
8018 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8019 if (SrcEltTy == SmallestEltTy)
8022 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8024 Src.WindowBase *= Src.WindowScale;
8029 for (
auto Src : Sources)
8030 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8038 if (
Entry.isUndef())
8047 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8050 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8054 int *LaneMask = &
Mask[i * ResMultiplier];
8056 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8057 ExtractBase += NumElts * (Src - Sources.begin());
8058 for (
int j = 0;
j < LanesDefined; ++
j)
8059 LaneMask[j] = ExtractBase + j;
8065 assert(Sources.size() <= 2 &&
"Too many sources!");
8068 for (
unsigned i = 0; i < Sources.size(); ++i)
8075 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8097 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8117 unsigned PFIndexes[4];
8118 for (
unsigned i = 0; i != 4; ++i) {
8122 PFIndexes[i] = M[i];
8126 unsigned PFTableIndex =
8127 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8129 unsigned Cost = (PFEntry >> 30);
8135 bool ReverseVEXT, isV_UNDEF;
8136 unsigned Imm, WhichResult;
8139 if (EltSize >= 32 ||
8146 else if (Subtarget->hasNEON() &&
8151 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8154 else if (Subtarget->hasMVEIntegerOps() &&
8158 else if (Subtarget->hasMVEIntegerOps() &&
8172 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8173 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8174 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8177 if (LHSID == (1*9+2)*9+3)
return LHS;
8178 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8192 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8195 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8198 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8203 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8208 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8235 for (
int I : ShuffleMask)
8239 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8, V1,
8242 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8, V1, V2,
8248 EVT VT =
Op.getValueType();
8250 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8251 "Expect an v8i16/v16i8 type");
8257 std::vector<int> NewMask;
8261 NewMask.push_back(i);
8291 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8301 if (VT != MVT::v16i1)
8302 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8312 return DAG.
getNode(ISD::BITCAST, dl, NewVT, PredAsVector);
8317 EVT VT =
Op.getValueType();
8321 assert(ST->hasMVEIntegerOps() &&
8322 "No support for vector shuffle of boolean predicates");
8332 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8348 "Expected identical vector type in expanded i1 shuffle!");
8352 PredAsVector2, ShuffleMask);
8357 if (VT == MVT::v2i1) {
8358 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8361 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8363 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8374 EVT VT =
Op.getValueType();
8378 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8379 "Unexpected vector type");
8381 int QuarterSize = NumElts / 4;
8390 for (
int i = 0; i <
Length; i++) {
8391 if (ShuffleMask[Start + i] >= 0) {
8392 if (ShuffleMask[Start + i] %
Length != i)
8394 MovIdx = ShuffleMask[Start + i] /
Length;
8402 for (
int i = 1; i <
Length; i++) {
8403 if (ShuffleMask[Start + i] >= 0 &&
8404 (ShuffleMask[Start + i] /
Length != MovIdx ||
8405 ShuffleMask[Start + i] %
Length != i))
8411 for (
int Part = 0; Part < 4; ++Part) {
8413 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8427 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8432 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8434 for (
int Part = 0; Part < 4; ++Part)
8435 for (
int i = 0; i < QuarterSize; i++)
8437 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8439 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8442 for (
int Part = 0; Part < 4; ++Part)
8458 EVT VT =
Op.getValueType();
8470 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8474 if (Mask[i] != i + BaseOffset) {
8475 if (OffElement == -1)
8481 return NonUndef > 2 && OffElement != -1;
8485 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8487 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8498 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8509 EVT VT =
Op.getValueType();
8513 if (ST->hasMVEIntegerOps() && EltSize == 1)
8524 if (EltSize <= 32) {
8528 if (Lane == -1) Lane = 0;
8539 bool IsScalarToVector =
true;
8542 IsScalarToVector =
false;
8545 if (IsScalarToVector)
8548 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT, V1,
8552 bool ReverseVEXT =
false;
8554 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8557 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V2,
8562 return DAG.
getNode(ARMISD::VREV64, dl, VT, V1);
8564 return DAG.
getNode(ARMISD::VREV32, dl, VT, V1);
8566 return DAG.
getNode(ARMISD::VREV16, dl, VT, V1);
8569 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V1,
8578 unsigned WhichResult = 0;
8579 bool isV_UNDEF =
false;
8580 if (ST->hasNEON()) {
8582 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8589 if (ST->hasMVEIntegerOps()) {
8591 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2, V1,
8594 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V2,
8597 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V1,
8624 }) &&
"Unexpected shuffle index into UNDEF operand!");
8627 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8630 assert((WhichResult == 0) &&
8631 "In-place shuffle of concat can only have one result!");
8640 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8644 for (
bool Top : {
false,
true}) {
8645 for (
bool SingleSource : {
false,
true}) {
8646 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8651 SingleSource ? V1 : V2);
8667 unsigned PFIndexes[4];
8668 for (
unsigned i = 0; i != 4; ++i) {
8669 if (ShuffleMask[i] < 0)
8672 PFIndexes[i] = ShuffleMask[i];
8676 unsigned PFTableIndex =
8677 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8679 unsigned Cost = (PFEntry >> 30);
8685 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8686 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8696 if (EltSize >= 32) {
8701 V1 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V1);
8702 V2 = DAG.
getNode(ISD::BITCAST, dl, VecVT, V2);
8704 for (
unsigned i = 0; i < NumElts; ++i) {
8705 if (ShuffleMask[i] < 0)
8709 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8714 return DAG.
getNode(ISD::BITCAST, dl, VT, Val);
8717 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8721 if (ST->hasNEON() && VT == MVT::v8i8)
8725 if (ST->hasMVEIntegerOps())
8734 EVT VecVT =
Op.getOperand(0).getValueType();
8737 assert(ST->hasMVEIntegerOps() &&
8738 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8741 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8742 unsigned Lane =
Op.getConstantOperandVal(2);
8743 unsigned LaneWidth =
8745 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8750 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8763 if (Subtarget->hasMVEIntegerOps() &&
8764 Op.getValueType().getScalarSizeInBits() == 1)
8788 IVecIn, IElt, Lane);
8789 return DAG.
getNode(ISD::BITCAST, dl, VecVT, IVecOut);
8797 EVT VecVT =
Op.getOperand(0).getValueType();
8800 assert(ST->hasMVEIntegerOps() &&
8801 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8804 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8805 unsigned Lane =
Op.getConstantOperandVal(1);
8806 unsigned LaneWidth =
8828 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8837 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8838 "Unexpected custom CONCAT_VECTORS lowering");
8840 "Unexpected custom CONCAT_VECTORS lowering");
8841 assert(ST->hasMVEIntegerOps() &&
8842 "CONCAT_VECTORS lowering only supported for MVE");
8846 EVT Op2VT = V2.getValueType();
8847 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8848 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8849 "Unexpected i1 concat operations!");
8862 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8867 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8876 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8877 EVT NewVT = NewV.getValueType();
8878 EVT ConcatVT = ConVec.getValueType();
8879 unsigned ExtScale = 1;
8880 if (NewVT == MVT::v2f64) {
8881 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8894 ConVec = ExtractInto(NewV1, ConVec, j);
8895 ConVec = ExtractInto(NewV2, ConVec, j);
8899 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8905 while (ConcatOps.
size() > 1) {
8906 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8909 ConcatOps[
I / 2] = ConcatPair(V1, V2);
8913 return ConcatOps[0];
8918 EVT VT =
Op->getValueType(0);
8924 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
8925 "unexpected CONCAT_VECTORS");
8932 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op0),
8936 DAG.
getNode(ISD::BITCAST, dl, MVT::f64, Op1),
8938 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Val);
8946 EVT VT =
Op.getValueType();
8952 "Unexpected custom EXTRACT_SUBVECTOR lowering");
8953 assert(ST->hasMVEIntegerOps() &&
8954 "EXTRACT_SUBVECTOR lowering only supported for MVE");
8964 EVT SubVT = MVT::v4i32;
8966 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
8976 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8981 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
8990 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
8997 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
8998 EVT VT =
N->getValueType(0);
8999 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9000 "Expected a vector i1 type!");
9002 EVT FromVT =
Op.getValueType();
9013 if (!Subtarget->hasMVEIntegerOps())
9016 EVT ToVT =
N->getValueType(0);
9059 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9061 EVT FromVT =
N->getOperand(0).getValueType();
9062 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9073 if (!Subtarget->hasMVEIntegerOps())
9078 EVT ToVT =
N->getValueType(0);
9079 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9082 EVT FromVT =
Op.getValueType();
9083 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9097 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9098 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9110 EVT VT =
N->getValueType(0);
9111 if (VT == MVT::v2i64 &&
N->getOpcode() == ISD::BITCAST) {
9112 SDNode *BVN =
N->getOperand(0).getNode();
9117 unsigned HiElt = 1 - LoElt;
9122 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9138 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9139 SDNode *Elt =
N->getOperand(i).getNode();
9142 unsigned HalfSize = EltSize / 2;
9144 if (!
isIntN(HalfSize,
C->getSExtValue()))
9147 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9186 switch (OrigSimpleTy) {
9202 unsigned ExtOpcode) {
9225 if (ExtendedTy == LD->getMemoryVT())
9226 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9227 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9228 LD->getMemOperand()->getFlags());
9234 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9235 LD->getMemoryVT(), LD->getAlign(),
9236 LD->getMemOperand()->getFlags());
9249 N->getOperand(0)->getValueType(0),
9255 "Expected extending load");
9261 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9269 if (
N->getOpcode() == ISD::BITCAST) {
9270 SDNode *BVN =
N->getOperand(0).getNode();
9272 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9280 EVT VT =
N->getValueType(0);
9286 for (
unsigned i = 0; i != NumElts; ++i) {
9287 const APInt &CInt =
N->getConstantOperandAPInt(i);
9296 unsigned Opcode =
N->getOpcode();
9298 SDNode *N0 =
N->getOperand(0).getNode();
9299 SDNode *N1 =
N->getOperand(1).getNode();
9307 unsigned Opcode =
N->getOpcode();
9309 SDNode *N0 =
N->getOperand(0).getNode();
9310 SDNode *N1 =
N->getOperand(1).getNode();
9320 EVT VT =
Op.getValueType();
9322 "unexpected type for custom-lowering ISD::MUL");
9323 SDNode *N0 =
Op.getOperand(0).getNode();
9324 SDNode *N1 =
Op.getOperand(1).getNode();
9325 unsigned NewOpc = 0;
9329 if (isN0SExt && isN1SExt)
9330 NewOpc = ARMISD::VMULLs;
9334 if (isN0ZExt && isN1ZExt)
9335 NewOpc = ARMISD::VMULLu;
9336 else if (isN1SExt || isN1ZExt) {
9340 NewOpc = ARMISD::VMULLs;
9343 NewOpc = ARMISD::VMULLu;
9347 NewOpc = ARMISD::VMULLu;
9353 if (VT == MVT::v2i64)
9370 "unexpected types for extended operands to VMULL");
9371 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9387 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N00), Op1),
9389 DAG.
getNode(ISD::BITCAST,
DL, Op1VT, N01), Op1));
9406 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9413 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32,
X);
9416 X = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32,
X);
9440 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9443 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9451 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9454 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9464 EVT VT =
Op.getValueType();
9465 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9466 "unexpected type for custom-lowering ISD::SDIV");
9473 if (VT == MVT::v8i8) {
9501 EVT VT =
Op.getValueType();
9502 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9503 "unexpected type for custom-lowering ISD::UDIV");
9510 if (VT == MVT::v8i8) {
9549 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9552 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9556 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9564 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, N0);
9567 N0 = DAG.
getNode(ISD::BITCAST, dl, MVT::v4f32, N0);
9577 EVT VT =
N->getValueType(0);
9590 Result = DAG.
getNode(ARMISD::ADDE,
DL, VTs,
Op.getOperand(0),
9591 Op.getOperand(1), Carry);
9604 Result = DAG.
getNode(ARMISD::SUBE,
DL, VTs,
Op.getOperand(0),
9605 Op.getOperand(1), Carry);
9622 EVT VT =
Op.getValueType();
9623 assert((VT == MVT::i32 || VT == MVT::i64) &&
9624 "unexpected type for custom lowering DIV");
9630 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9632 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9639 for (
auto AI : {1, 0}) {
9641 Args.emplace_back(Operand,
9649 ES, std::move(Args));
9659ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9667 const bool MinSize =
ST.hasMinSize();
9668 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9669 :
ST.hasDivideInARMMode();
9673 if (
N->getOperand(0).getValueType().isVector())
9678 if (!(MinSize && HasDivide))
9691 if (Divisor.
sgt(128))
9699 assert(
Op.getValueType() == MVT::i32 &&
9700 "unexpected type for custom lowering DIV");
9703 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9706 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9712 if (
N->getValueType(0) == MVT::i32)
9713 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9716 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9720void ARMTargetLowering::ExpandDIV_Windows(
9725 assert(
Op.getValueType() == MVT::i64 &&
9726 "unexpected type for custom lowering DIV");
9743 EVT MemVT = LD->getMemoryVT();
9744 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9745 MemVT == MVT::v16i1) &&
9746 "Expected a predicate type!");
9747 assert(MemVT ==
Op.getValueType());
9749 "Expected a non-extending load");
9750 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9764 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9766 LD->getMemOperand());
9772 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9773 if (MemVT != MVT::v16i1)
9782 EVT MemVT =
LD->getMemoryVT();
9783 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9785 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9786 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9787 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9790 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9791 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9801 EVT MemVT = ST->getMemoryVT();
9802 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9803 MemVT == MVT::v16i1) &&
9804 "Expected a predicate type!");
9805 assert(MemVT == ST->getValue().getValueType());
9806 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9807 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9812 SDValue Build = ST->getValue();
9813 if (MemVT != MVT::v16i1) {
9826 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9832 ST->getChain(), dl, GRP, ST->getBasePtr(),
9834 ST->getMemOperand());
9840 EVT MemVT = ST->getMemoryVT();
9841 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
9843 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9859 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
9860 MemVT, ST->getMemOperand());
9861 }
else if (Subtarget->hasMVEIntegerOps() &&
9862 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9863 MemVT == MVT::v16i1))) {
9872 (
N->getOpcode() == ARMISD::VMOVIMM &&
9878 MVT VT =
Op.getSimpleValueType();
9880 SDValue PassThru =
N->getPassThru();
9891 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
9892 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
9893 N->getExtensionType(),
N->isExpandingLoad());
9895 bool PassThruIsCastZero = (PassThru.
getOpcode() == ISD::BITCAST ||
9896 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
9898 if (!PassThru.
isUndef() && !PassThruIsCastZero)
9905 if (!ST->hasMVEIntegerOps())
9909 unsigned BaseOpcode = 0;
9910 switch (
Op->getOpcode()) {
9912 case ISD::VECREDUCE_FADD: BaseOpcode =
ISD::FADD;
break;
9913 case ISD::VECREDUCE_FMUL: BaseOpcode =
ISD::FMUL;
break;
9914 case ISD::VECREDUCE_MUL: BaseOpcode =
ISD::MUL;
break;
9915 case ISD::VECREDUCE_AND: BaseOpcode =
ISD::AND;
break;
9916 case ISD::VECREDUCE_OR: BaseOpcode =
ISD::OR;
break;
9917 case ISD::VECREDUCE_XOR: BaseOpcode =
ISD::XOR;
break;
9918 case ISD::VECREDUCE_FMAX: BaseOpcode = ISD::FMAXNUM;
break;
9919 case ISD::VECREDUCE_FMIN: BaseOpcode = ISD::FMINNUM;
break;
9926 unsigned NumActiveLanes = NumElts;
9928 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
9929 NumActiveLanes == 2) &&
9930 "Only expected a power 2 vector size");
9934 while (NumActiveLanes > 4) {
9935 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
9937 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
9938 NumActiveLanes /= 2;
9942 if (NumActiveLanes == 4) {
9952 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
9953 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
9954 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
9960 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
9964 if (EltVT !=
Op->getValueType(0))
9971 if (!ST->hasMVEFloatOps())
9986 unsigned PairwiseIntrinsic = 0;
9987 switch (
Op->getOpcode()) {
9990 case ISD::VECREDUCE_UMIN:
9991 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
9993 case ISD::VECREDUCE_UMAX:
9994 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
9996 case ISD::VECREDUCE_SMIN:
9997 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
9999 case ISD::VECREDUCE_SMAX:
10000 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10006 unsigned NumActiveLanes = NumElts;
10008 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10009 NumActiveLanes == 2) &&
10010 "Only expected a power 2 vector size");
10016 VT =
Lo.getValueType();
10018 NumActiveLanes /= 2;
10022 while (NumActiveLanes > 1) {
10024 NumActiveLanes /= 2;
10031 if (EltVT !=
Op.getValueType()) {
10032 unsigned Extend = 0;
10033 switch (
Op->getOpcode()) {
10036 case ISD::VECREDUCE_UMIN:
10037 case ISD::VECREDUCE_UMAX:
10040 case ISD::VECREDUCE_SMIN:
10041 case ISD::VECREDUCE_SMAX:
10045 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10090 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10096 SDLoc dl(V.getNode());
10097 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10107 assert(
N->getValueType(0) == MVT::i64 &&
10108 "AtomicCmpSwap on types less than 64 should be legal");
10117 ARM::CMP_SWAP_64,
SDLoc(
N),
10118 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10137 EVT VT =
Op.getValueType();
10146 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10148 Chain, IsSignaling);
10149 if (!
RHS.getNode()) {
10165 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10167 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10168 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10185 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10188 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10201 if (!IsSigned && Subtarget->isThumb1Only()) {
10219 Sub1Result, Sub1Result, Flags1);
10234 if (
Op.getValueType() != MVT::i32)
10248 unsigned Opcode = ARMISD::SUBC;
10257 bool CanUseAdd =
false;
10273 Opcode = ARMISD::ADDC;
10297 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10298 GTCondValue, Flags);
10302 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10303 LTCondValue, Flags);
10305 if (
Op.getValueType() != MVT::i32)
10313 switch (
Op.getOpcode()) {
10322 case ISD::BRCOND:
return LowerBRCOND(
Op, DAG);
10323 case ISD::BR_CC:
return LowerBR_CC(
Op, DAG);
10324 case ISD::BR_JT:
return LowerBR_JT(
Op, DAG);
10345 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10349 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10350 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10370 case ISD::SET_ROUNDING:
return LowerSET_ROUNDING(
Op, DAG);
10371 case ISD::SET_FPMODE:
10372 return LowerSET_FPMODE(
Op, DAG);
10373 case ISD::RESET_FPMODE:
10374 return LowerRESET_FPMODE(
Op, DAG);
10377 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10378 return LowerDIV_Windows(
Op, DAG,
true);
10381 if (Subtarget->isTargetWindows() && !
Op.getValueType().isVector())
10382 return LowerDIV_Windows(
Op, DAG,
false);
10389 return LowerSignedALUO(
Op, DAG);
10392 return LowerUnsignedALUO(
Op, DAG);
10404 case ISD::VECREDUCE_MUL:
10405 case ISD::VECREDUCE_AND:
10406 case ISD::VECREDUCE_OR:
10407 case ISD::VECREDUCE_XOR:
10409 case ISD::VECREDUCE_FADD:
10410 case ISD::VECREDUCE_FMUL:
10411 case ISD::VECREDUCE_FMIN:
10412 case ISD::VECREDUCE_FMAX:
10414 case ISD::VECREDUCE_UMIN:
10415 case ISD::VECREDUCE_UMAX:
10416 case ISD::VECREDUCE_SMIN:
10417 case ISD::VECREDUCE_SMAX:
10419 case ISD::ATOMIC_LOAD:
10420 case ISD::ATOMIC_STORE:
10424 case ISD::DYNAMIC_STACKALLOC:
10425 if (Subtarget->isTargetWindows())
10426 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10431 case ISD::FP_EXTEND:
return LowerFP_EXTEND(
Op, DAG);
10435 return LowerSPONENTRY(
Op, DAG);
10436 case ISD::FP_TO_BF16:
10437 return LowerFP_TO_BF16(
Op, DAG);
10438 case ARMISD::WIN__DBZCHK:
return SDValue();
10441 return LowerCMP(
Op, DAG);
10443 return LowerABS(
Op, DAG);
10448 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10449 Op.getOperand(1).getValueType() == MVT::bf16) &&
10450 "Expected custom lowering of rounding operations only for f16");
10453 {
Op.getOperand(0),
Op.getOperand(1)});
10454 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10455 {Ext.getValue(1), Ext.getValue(0)});
10462 unsigned IntNo =
N->getConstantOperandVal(0);
10464 if (IntNo == Intrinsic::arm_smlald)
10465 Opc = ARMISD::SMLALD;
10466 else if (IntNo == Intrinsic::arm_smlaldx)
10467 Opc = ARMISD::SMLALDX;
10468 else if (IntNo == Intrinsic::arm_smlsld)
10469 Opc = ARMISD::SMLSLD;
10470 else if (IntNo == Intrinsic::arm_smlsldx)
10471 Opc = ARMISD::SMLSLDX;
10477 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10481 N->getOperand(1),
N->getOperand(2),
10493 switch (
N->getOpcode()) {
10500 Res = ExpandBITCAST(
N, DAG, Subtarget);
10509 Res = LowerREM(
N, DAG);
10513 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10524 case ISD::READCYCLECOUNTER:
10529 assert(Subtarget->isTargetWindows() &&
"can only expand DIV on Windows");
10532 case ISD::ATOMIC_CMP_SWAP:
10567 "ROPI/RWPI not currently supported with SjLj");
10576 bool isThumb = Subtarget->isThumb();
10577 bool isThumb2 = Subtarget->
isThumb2();
10580 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10586 : &ARM::GPRRegClass;
10604 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10610 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10616 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10634 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10639 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10644 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10649 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10655 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10670 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10676 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10692 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10699 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10700 : &ARM::GPRnopcRegClass;
10704 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10705 unsigned MaxCSNum = 0;
10706 for (MachineBasicBlock &BB : *MF) {
10712 for (MachineInstr &
II : BB) {
10713 if (!
II.isEHLabel())
10716 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10717 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10719 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10720 for (
unsigned Idx : CallSiteIdxs) {
10721 CallSiteNumToLPad[Idx].push_back(&BB);
10722 MaxCSNum = std::max(MaxCSNum, Idx);
10729 std::vector<MachineBasicBlock*> LPadList;
10730 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10731 LPadList.reserve(CallSiteNumToLPad.
size());
10732 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10733 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10734 for (MachineBasicBlock *
MBB : MBBList) {
10735 LPadList.push_back(
MBB);
10740 assert(!LPadList.empty() &&
10741 "No landing pad destinations for the dispatch jump table!");
10744 MachineJumpTableInfo *JTI =
10751 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10754 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10756 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10759 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10763 MF->insert(MF->end(), DispatchBB);
10764 MF->insert(MF->end(), DispContBB);
10765 MF->insert(MF->end(), TrapBB);
10769 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10771 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10775 MachineInstrBuilder MIB;
10776 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10778 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10788 unsigned NumLPads = LPadList.size();
10789 if (Subtarget->isThumb2()) {
10790 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10791 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10797 if (NumLPads < 256) {
10798 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10800 .
addImm(LPadList.size())
10803 Register VReg1 =
MRI->createVirtualRegister(TRC);
10804 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10805 .
addImm(NumLPads & 0xFFFF)
10808 unsigned VReg2 = VReg1;
10809 if ((NumLPads & 0xFFFF0000) != 0) {
10810 VReg2 =
MRI->createVirtualRegister(TRC);
10811 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10817 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
10823 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
10828 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10829 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
10833 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10834 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
10841 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
10845 }
else if (Subtarget->isThumb()) {
10846 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10847 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
10853 if (NumLPads < 256) {
10854 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
10859 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10864 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
10865 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
10867 Register VReg1 =
MRI->createVirtualRegister(TRC);
10868 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
10872 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
10878 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
10883 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10884 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
10890 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10891 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
10895 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10896 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
10902 MachineMemOperand *JTMMOLd =
10906 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10907 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
10913 unsigned NewVReg6 = NewVReg5;
10914 if (IsPositionIndependent) {
10915 NewVReg6 =
MRI->createVirtualRegister(TRC);
10916 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
10923 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
10927 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10928 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
10934 if (NumLPads < 256) {
10935 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
10939 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
10940 Register VReg1 =
MRI->createVirtualRegister(TRC);
10941 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
10942 .
addImm(NumLPads & 0xFFFF)
10945 unsigned VReg2 = VReg1;
10946 if ((NumLPads & 0xFFFF0000) != 0) {
10947 VReg2 =
MRI->createVirtualRegister(TRC);
10948 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
10954 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
10959 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10964 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
10965 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
10967 Register VReg1 =
MRI->createVirtualRegister(TRC);
10968 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
10973 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
10984 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10985 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
10990 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10991 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
10995 MachineMemOperand *JTMMOLd =
10998 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10999 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11006 if (IsPositionIndependent) {
11007 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11012 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11019 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11020 for (MachineBasicBlock *CurMBB : LPadList) {
11021 if (SeenMBBs.
insert(CurMBB).second)
11028 for (MachineBasicBlock *BB : InvokeBBs) {
11032 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11033 while (!Successors.empty()) {
11034 MachineBasicBlock *SMBB = Successors.pop_back_val();
11036 BB->removeSuccessor(SMBB);
11042 BB->normalizeSuccProbs();
11049 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11050 if (!
II->isCall())
continue;
11052 DenseSet<unsigned> DefRegs;
11054 OI =
II->operands_begin(), OE =
II->operands_end();
11056 if (!OI->isReg())
continue;
11057 DefRegs.
insert(OI->getReg());
11060 MachineInstrBuilder MIB(*MF, &*
II);
11062 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11063 unsigned Reg = SavedRegs[i];
11064 if (Subtarget->isThumb2() &&
11065 !ARM::tGPRRegClass.contains(
Reg) &&
11066 !ARM::hGPRRegClass.contains(
Reg))
11068 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11070 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11082 for (MachineBasicBlock *MBBLPad : MBBLPads)
11083 MBBLPad->setIsEHPad(
false);
11086 MI.eraseFromParent();
11099static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11101 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11102 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11104 return LdSize == 4 ? ARM::tLDRi
11105 : LdSize == 2 ? ARM::tLDRHi
11106 : LdSize == 1 ? ARM::tLDRBi : 0;
11108 return LdSize == 4 ? ARM::t2LDR_POST
11109 : LdSize == 2 ? ARM::t2LDRH_POST
11110 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11111 return LdSize == 4 ? ARM::LDR_POST_IMM
11112 : LdSize == 2 ? ARM::LDRH_POST
11113 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11118static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11120 return StSize == 16 ? ARM::VST1q32wb_fixed
11121 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11123 return StSize == 4 ? ARM::tSTRi
11124 : StSize == 2 ? ARM::tSTRHi
11125 : StSize == 1 ? ARM::tSTRBi : 0;
11127 return StSize == 4 ? ARM::t2STR_POST
11128 : StSize == 2 ? ARM::t2STRH_POST
11129 : StSize == 1 ? ARM::t2STRB_POST : 0;
11130 return StSize == 4 ? ARM::STR_POST_IMM
11131 : StSize == 2 ? ARM::STRH_POST
11132 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11139 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11140 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11141 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11142 assert(LdOpc != 0 &&
"Should have a load opcode");
11149 }
else if (IsThumb1) {
11155 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11160 }
else if (IsThumb2) {
11180 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11181 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11182 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11183 assert(StOpc != 0 &&
"Should have a store opcode");
11185 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11190 }
else if (IsThumb1) {
11197 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11202 }
else if (IsThumb2) {
11203 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11209 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11224 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11230 unsigned SizeVal =
MI.getOperand(2).getImm();
11231 unsigned Alignment =
MI.getOperand(3).getImm();
11236 unsigned UnitSize = 0;
11237 const TargetRegisterClass *TRC =
nullptr;
11238 const TargetRegisterClass *VecTRC =
nullptr;
11240 bool IsThumb1 = Subtarget->isThumb1Only();
11241 bool IsThumb2 = Subtarget->isThumb2();
11242 bool IsThumb = Subtarget->isThumb();
11244 if (Alignment & 1) {
11246 }
else if (Alignment & 2) {
11251 Subtarget->hasNEON()) {
11252 if ((Alignment % 16 == 0) && SizeVal >= 16)
11254 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11263 bool IsNeon = UnitSize >= 8;
11264 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11266 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11267 : UnitSize == 8 ? &ARM::DPRRegClass
11270 unsigned BytesLeft = SizeVal % UnitSize;
11271 unsigned LoopSize = SizeVal - BytesLeft;
11273 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11277 unsigned srcIn = src;
11278 unsigned destIn = dest;
11279 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11280 Register srcOut =
MRI.createVirtualRegister(TRC);
11281 Register destOut =
MRI.createVirtualRegister(TRC);
11282 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11284 IsThumb1, IsThumb2);
11286 IsThumb1, IsThumb2);
11294 for (
unsigned i = 0; i < BytesLeft; i++) {
11295 Register srcOut =
MRI.createVirtualRegister(TRC);
11296 Register destOut =
MRI.createVirtualRegister(TRC);
11297 Register scratch =
MRI.createVirtualRegister(TRC);
11299 IsThumb1, IsThumb2);
11301 IsThumb1, IsThumb2);
11305 MI.eraseFromParent();
11331 MF->
insert(It, loopMBB);
11332 MF->
insert(It, exitMBB);
11335 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11345 Register varEnd =
MRI.createVirtualRegister(TRC);
11346 if (Subtarget->useMovt()) {
11347 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11350 }
else if (Subtarget->genExecuteOnly()) {
11351 assert(IsThumb &&
"Non-thumb expected to have used movt");
11360 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11361 MachineMemOperand *CPMMO =
11385 MachineBasicBlock *entryBB = BB;
11387 Register varLoop =
MRI.createVirtualRegister(TRC);
11388 Register varPhi =
MRI.createVirtualRegister(TRC);
11389 Register srcLoop =
MRI.createVirtualRegister(TRC);
11390 Register srcPhi =
MRI.createVirtualRegister(TRC);
11391 Register destLoop =
MRI.createVirtualRegister(TRC);
11392 Register destPhi =
MRI.createVirtualRegister(TRC);
11400 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11406 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11408 IsThumb1, IsThumb2);
11410 IsThumb1, IsThumb2);
11414 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11420 MachineInstrBuilder MIB =
11422 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11431 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11440 auto StartOfExit = exitMBB->
begin();
11444 unsigned srcIn = srcLoop;
11445 unsigned destIn = destLoop;
11446 for (
unsigned i = 0; i < BytesLeft; i++) {
11447 Register srcOut =
MRI.createVirtualRegister(TRC);
11448 Register destOut =
MRI.createVirtualRegister(TRC);
11449 Register scratch =
MRI.createVirtualRegister(TRC);
11450 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11451 IsThumb1, IsThumb2);
11452 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11453 IsThumb1, IsThumb2);
11458 MI.eraseFromParent();
11466 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11469 assert(Subtarget->isTargetWindows() &&
11470 "__chkstk is only supported on Windows");
11471 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11491 switch (TM.getCodeModel()) {
11533 MI.eraseFromParent();
11542 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11557 .
addReg(
MI.getOperand(0).getReg())
11565 MI.eraseFromParent();
11589 if (miI == BB->
end()) {
11591 if (Succ->isLiveIn(ARM::CPSR))
11597 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11609 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11610 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11616 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11617 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11623 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11624 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11627 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11628 .
addUse(TotalIterationsReg)
11635 return TotalIterationsReg;
11646 Register TotalIterationsReg,
bool IsMemcpy) {
11653 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11654 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11655 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11663 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11664 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11665 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11672 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11673 Register RemainingLoopIterationsReg =
11674 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11675 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11676 .
addUse(TotalIterationsReg)
11678 .
addUse(RemainingLoopIterationsReg)
11682 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11683 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11684 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11685 .
addUse(ElementCountReg)
11687 .
addUse(RemainingElementsReg)
11691 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11692 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11693 .
addUse(PredCounterPhiReg)
11698 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11699 .
addUse(PredCounterPhiReg)
11707 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11708 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11717 SrcValueReg = OpSrcReg;
11719 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11730 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11731 .
addUse(LoopCounterPhiReg)
11734 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11735 .
addUse(RemainingLoopIterationsReg)
11753 "Invalid call instruction for a KCFI check");
11756 switch (
MBBI->getOpcode()) {
11759 case ARM::BLX_pred:
11760 case ARM::BLX_noip:
11761 case ARM::BLX_pred_noip:
11763 TargetOp = &
MBBI->getOperand(0);
11765 case ARM::TCRETURNri:
11766 case ARM::TCRETURNrinotr12:
11767 case ARM::TAILJMPr:
11768 case ARM::TAILJMPr4:
11769 TargetOp = &
MBBI->getOperand(0);
11775 case ARM::tBLXr_noip:
11776 case ARM::tBX_CALL:
11777 TargetOp = &
MBBI->getOperand(2);
11780 case ARM::tTAILJMPr:
11781 TargetOp = &
MBBI->getOperand(0);
11787 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11791 unsigned KCFICheckOpcode;
11792 if (Subtarget->isThumb()) {
11793 if (Subtarget->isThumb2()) {
11794 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11796 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11799 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11813 bool isThumb2 = Subtarget->isThumb2();
11814 switch (
MI.getOpcode()) {
11821 case ARM::tLDR_postidx: {
11825 .
add(
MI.getOperand(2))
11826 .
add(
MI.getOperand(3))
11827 .
add(
MI.getOperand(4))
11828 .
add(
MI.getOperand(0))
11830 MI.eraseFromParent();
11834 case ARM::MVE_MEMCPYLOOPINST:
11835 case ARM::MVE_MEMSETLOOPINST: {
11865 Register OpDestReg =
MI.getOperand(0).getReg();
11866 Register OpSrcReg =
MI.getOperand(1).getReg();
11867 Register OpSizeReg =
MI.getOperand(2).getReg();
11887 if (TpExit == BB) {
11889 "block containing memcpy/memset Pseudo");
11902 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
11904 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
11907 Properties.resetNoPHIs();
11919 MI.eraseFromParent();
11929 case ARM::t2STR_preidx:
11930 MI.setDesc(
TII->get(ARM::t2STR_PRE));
11932 case ARM::t2STRB_preidx:
11933 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
11935 case ARM::t2STRH_preidx:
11936 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
11939 case ARM::STRi_preidx:
11940 case ARM::STRBi_preidx: {
11941 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
11942 : ARM::STRB_PRE_IMM;
11944 unsigned Offset =
MI.getOperand(4).getImm();
11952 .
add(
MI.getOperand(0))
11953 .
add(
MI.getOperand(1))
11954 .
add(
MI.getOperand(2))
11956 .
add(
MI.getOperand(5))
11957 .
add(
MI.getOperand(6))
11959 MI.eraseFromParent();
11962 case ARM::STRr_preidx:
11963 case ARM::STRBr_preidx:
11964 case ARM::STRH_preidx: {
11966 switch (
MI.getOpcode()) {
11968 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
11969 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
11970 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
11975 MI.eraseFromParent();
11979 case ARM::tMOVCCr_pseudo: {
11997 F->insert(It, copy0MBB);
11998 F->insert(It, sinkMBB);
12001 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12007 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12023 .
addImm(
MI.getOperand(3).getImm())
12024 .
addReg(
MI.getOperand(4).getReg());
12039 .
addReg(
MI.getOperand(1).getReg())
12041 .
addReg(
MI.getOperand(2).getReg())
12044 MI.eraseFromParent();
12049 case ARM::BCCZi64: {
12055 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12060 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12064 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12070 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12074 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12084 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12093 MI.eraseFromParent();
12097 case ARM::Int_eh_sjlj_setjmp:
12098 case ARM::Int_eh_sjlj_setjmp_nofp:
12099 case ARM::tInt_eh_sjlj_setjmp:
12100 case ARM::t2Int_eh_sjlj_setjmp:
12101 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12104 case ARM::Int_eh_sjlj_setup_dispatch:
12105 EmitSjLjDispatchBlock(
MI, BB);
12107 case ARM::COPY_STRUCT_BYVAL_I32:
12109 return EmitStructByval(
MI, BB);
12110 case ARM::WIN__CHKSTK:
12111 return EmitLowered__chkstk(
MI, BB);
12112 case ARM::WIN__DBZCHK:
12113 return EmitLowered__dbzchk(
MI, BB);
12129 if (!
Node->hasAnyUseOfValue(0)) {
12130 MI.getOperand(0).setIsDead(
true);
12132 if (!
Node->hasAnyUseOfValue(1)) {
12133 MI.getOperand(1).setIsDead(
true);
12137 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12138 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12139 : &ARM::GPRRegClass);
12146 if (
MI.getOpcode() == ARM::MEMCPY) {
12167 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12168 &&
"converted opcode should be the same except for cc_out"
12169 " (and, on Thumb1, pred)");
12177 if (Subtarget->isThumb1Only()) {
12178 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12179 MI.addOperand(
MI.getOperand(1));
12180 MI.removeOperand(1);
12184 for (
unsigned i =
MI.getNumOperands(); i--;) {
12186 if (
op.isReg() &&
op.isUse()) {
12189 MI.tieOperands(DefIdx, i);
12197 ccOutIdx =
MCID->getNumOperands() - 1;
12199 ccOutIdx =
MCID->getNumOperands() - 1;
12203 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12204 assert(!NewOpc &&
"Optional cc_out operand required");
12209 bool definesCPSR =
false;
12210 bool deadCPSR =
false;
12211 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12215 definesCPSR =
true;
12218 MI.removeOperand(i);
12222 if (!definesCPSR) {
12223 assert(!NewOpc &&
"Optional cc_out operand required");
12226 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12228 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12229 "expect uninitialized optional cc_out operand");
12231 if (!Subtarget->isThumb1Only())
12267 switch (
N->getOpcode()) {
12268 default:
return false;
12270 CC =
N->getOperand(0);
12292 EVT VT =
N->getValueType(0);
12293 CC =
N->getOperand(0);
12340 EVT VT =
N->getValueType(0);
12343 bool SwapSelectOps;
12345 NonConstantVal, DAG))
12351 OtherOp, NonConstantVal);
12357 CCOp, TrueVal, FalseVal);
12377 if (
N->getOpcode() == ARMISD::VUZP)
12381 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12396 if (!
N->getValueType(0).is64BitVector())
12404 EVT VT =
N->getValueType(0);
12443 EVT VT =
N->getValueType(0);
12449 Opcode = Intrinsic::arm_neon_vpaddls;
12451 Opcode = Intrinsic::arm_neon_vpaddlu;
12479 EVT VT =
N->getValueType(0);
12494 unsigned nextIndex = 0;
12545 Ops.push_back(Vec);
12562 return DAG.
getNode(ExtOp, dl, VT, tmp);
12593 if (SRA.getOpcode() !=
ISD::SRA) {
12600 if (Const->getZExtValue() != 31)
12605 if (SRA.getOperand(0) !=
Mul)
12609 SDLoc dl(AddcNode);
12610 unsigned Opcode = 0;
12615 Opcode = ARMISD::SMLALBB;
12616 Op0 =
Mul.getOperand(0);
12617 Op1 =
Mul.getOperand(1);
12619 Opcode = ARMISD::SMLALBT;
12620 Op0 =
Mul.getOperand(0);
12621 Op1 =
Mul.getOperand(1).getOperand(0);
12623 Opcode = ARMISD::SMLALTB;
12624 Op0 =
Mul.getOperand(0).getOperand(0);
12625 Op1 =
Mul.getOperand(1);
12627 Opcode = ARMISD::SMLALTT;
12628 Op0 =
Mul->getOperand(0).getOperand(0);
12629 Op1 =
Mul->getOperand(1).getOperand(0);
12645 SDValue resNode(AddcNode, 0);
12673 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12674 "Expect an ADDE or SUBE");
12678 "ADDE node has the wrong inputs");
12682 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12683 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12684 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12685 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12697 "Expect ADDC with two result values. First: i32");
12701 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12717 bool IsLeftOperandMUL =
false;
12722 IsLeftOperandMUL =
true;
12733 SDValue *LowAddSub =
nullptr;
12736 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12739 if (IsLeftOperandMUL)
12740 HiAddSub = &AddeSubeOp1;
12742 HiAddSub = &AddeSubeOp0;
12747 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12748 LoMul = &AddcSubcOp0;
12749 LowAddSub = &AddcSubcOp1;
12751 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12752 LoMul = &AddcSubcOp1;
12753 LowAddSub = &AddcSubcOp0;
12761 if (AddcSubcNode == HiAddSub->getNode() ||
12777 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12782 Ops.push_back(*HiAddSub);
12783 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12784 FinalOpc = ARMISD::SMMLSR;
12786 FinalOpc = ARMISD::SMMLAR;
12791 return SDValue(AddeSubeNode, 0);
12792 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12798 Ops.push_back(*LowAddSub);
12799 Ops.push_back(*HiAddSub);
12812 return SDValue(AddeSubeNode, 0);
12824 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12829 if (AddcNode->
getOpcode() != ARMISD::ADDC)
12833 SDNode *UmlalNode =
nullptr;
12872 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12877 SDNode* AddcNode =
N->getOperand(2).getNode();
12878 SDNode* AddeNode =
N->getOperand(3).getNode();
12879 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
12880 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
12886 {N->getOperand(0), N->getOperand(1),
12887 AddcNode->getOperand(0), AddcNode->getOperand(1)});
12897 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
12901 if (
LHS->getOpcode() == ARMISD::ADDE &&
12911 int32_t imm =
C->getSExtValue();
12912 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
12915 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
12917 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
12932 int64_t imm =
C->getSExtValue();
12941 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
12943 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
12944 N->getOperand(0),
RHS,
N->getOperand(2));
12956 if (!Subtarget->hasMVEIntegerOps())
12969 SetCC =
N->getOperand(0);
12973 TrueVal =
N->getOperand(1);
12974 FalseVal =
N->getOperand(2);
12976 LHS =
N->getOperand(0);
12977 RHS =
N->getOperand(1);
12979 TrueVal =
N->getOperand(2);
12980 FalseVal =
N->getOperand(3);
12985 unsigned int Opcode = 0;
12986 if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMIN ||
12987 FalseVal->getOpcode() == ISD::VECREDUCE_UMIN) &&
12989 Opcode = ARMISD::VMINVu;
12992 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMIN ||
12993 FalseVal->getOpcode() == ISD::VECREDUCE_SMIN) &&
12995 Opcode = ARMISD::VMINVs;
12998 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_UMAX ||
12999 FalseVal->getOpcode() == ISD::VECREDUCE_UMAX) &&
13001 Opcode = ARMISD::VMAXVu;
13004 }
else if ((TrueVal->getOpcode() == ISD::VECREDUCE_SMAX ||
13005 FalseVal->getOpcode() == ISD::VECREDUCE_SMAX) &&
13007 Opcode = ARMISD::VMAXVs;
13014 switch (TrueVal->getOpcode()) {
13015 case ISD::VECREDUCE_UMIN:
13016 case ISD::VECREDUCE_SMIN:
13017 case ISD::VECREDUCE_UMAX:
13018 case ISD::VECREDUCE_SMAX:
13033 if (TrueVal !=
LHS || FalseVal !=
RHS)
13036 EVT LeftType =
LHS->getValueType(0);
13037 EVT RightType =
RHS->getValueType(0);
13040 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13044 if (VectorScalarType != MVT::i32)
13052 if (VectorScalarType != MVT::i32)
13065 EVT VT =
N->getValueType(0);
13073 Shft =
N->getOperand(0);
13080 Cmp.getOperand(0) !=
N->getOperand(1) ||
13081 Cmp.getOperand(1) !=
N->getOperand(2))
13083 Shft =
N->getOperand(1);
13095 ScalarType = MVT::i8;
13098 case (1 << 15) - 1:
13099 ScalarType = MVT::i16;
13102 case (1ULL << 31) - 1:
13103 ScalarType = MVT::i32;
13134 unsigned LegalLanes = 128 / (ShftAmt + 1);
13146 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13147 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13148 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13149 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13158 for (
unsigned I = 0;
I < NumParts; ++
I) {
13165 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13175 if (!Subtarget->hasMVEIntegerOps())
13190 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13200 if (!Const || !Const->isOne())
13218 EVT VT =
N->getValueType(0);
13220 if (!Subtarget->hasMVEIntegerOps() ||
13249 Opc = Intrinsic::arm_mve_vctp64;
13252 Opc = Intrinsic::arm_mve_vctp32;
13255 Opc = Intrinsic::arm_mve_vctp16;
13258 Opc = Intrinsic::arm_mve_vctp8;
13312 EVT VT =
N->getValueType(0);
13318 switch (
Op.getOpcode()) {
13319 case ISD::VECREDUCE_ADD:
13320 case ARMISD::VADDVs:
13321 case ARMISD::VADDVu:
13322 case ARMISD::VMLAVs:
13323 case ARMISD::VMLAVu:
13343 unsigned N0RedOp = 0;
13350 unsigned N1RedOp = 0;
13364 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13366 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13373 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13397 if (!BaseLocDecomp0.getBase() ||
13398 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13399 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13401 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13403 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13413 if (IsBefore < 0) {
13416 }
else if (IsBefore > 0) {
13429 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13439 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13449 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13451 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13458 if (!Subtarget->hasMVEIntegerOps())
13464 EVT VT =
N->getValueType(0);
13469 if (VT != MVT::i64)
13480 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13500 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13509 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13511 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13513 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13515 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13517 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13519 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13521 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13523 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13525 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13527 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13529 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13531 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13533 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13535 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13537 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13539 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13549 "Expected shift op");
13551 SDValue ShiftLHS =
N->getOperand(0);
13565 if (Subtarget->isThumb1Only()) {
13576 if (Const->getAPIntValue().ult(256))
13579 Const->getAPIntValue().sgt(-256))
13595 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13596 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13597 "Expected XOR(SHIFT) pattern");
13602 if (XorC && ShiftC) {
13603 unsigned MaskIdx, MaskLen;
13604 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13605 unsigned ShiftAmt = ShiftC->getZExtValue();
13606 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13607 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13608 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13609 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13619 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13621 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13622 "Expected shift-shift mask");
13624 if (!Subtarget->isThumb1Only())
13627 EVT VT =
N->getValueType(0);
13635 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13637 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13642 if (!Subtarget->hasNEON()) {
13643 if (Subtarget->isThumb1Only())
13657 return Subtarget->hasVFP2Base();
13659 return Subtarget->hasVFP2Base();
13661 return Subtarget->hasFP64();
13664 return Subtarget->hasMVEFloatOps();
13693 if (ST->isThumb() && ST->isThumb1Only())
13697 for (
auto *U :
N->users()) {
13698 switch(U->getOpcode()) {
13716 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13717 U->getOperand(1).getOpcode() ==
ISD::SHL)
13727 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13734 if (!C1ShlC2 || !C2)
13737 APInt C2Int = C2->getAPIntValue();
13738 APInt C1Int = C1ShlC2->getAPIntValue();
13740 if (C2Int.
uge(C2Width))
13746 if ((C1Int & Mask) != C1Int)
13753 auto LargeImm = [](
const APInt &Imm) {
13754 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13755 return Imm.getBitWidth() - Zeros > 8;
13758 if (LargeImm(C1Int) || LargeImm(C2Int))
13770 SHL.dump();
N->dump());
13873 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
13894 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
13915 if (!Subtarget->hasVMLxForwarding())
13934 EVT VT =
N->getValueType(0);
13945 EVT VT =
N->getValueType(0);
13946 if (VT != MVT::v2i64)
13957 return Op->getOperand(0);
13970 if (
And->getOpcode() == ISD::BITCAST)
13971 And =
And->getOperand(0);
13975 if (Mask->getOpcode() == ISD::BITCAST)
13976 Mask = Mask->getOperand(0);
13979 Mask.getValueType() != MVT::v4i32)
13985 return And->getOperand(0);
13990 if (
SDValue Op0 = IsSignExt(N0)) {
13991 if (
SDValue Op1 = IsSignExt(N1)) {
13992 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
13993 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
13994 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
13997 if (
SDValue Op0 = IsZeroExt(N0)) {
13998 if (
SDValue Op1 = IsZeroExt(N1)) {
13999 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14000 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14001 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14013 EVT VT =
N->getValueType(0);
14014 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14025 if (VT != MVT::i32)
14032 int64_t MulAmt =
C->getSExtValue();
14035 ShiftAmt = ShiftAmt & (32 - 1);
14040 MulAmt >>= ShiftAmt;
14101 if (
N->getValueType(0) != MVT::i32)
14110 if (C1 == 255 || C1 == 65535)
14113 SDNode *N0 =
N->getOperand(0).getNode();
14127 if (!C2 || C2 >= 32)
14171 if (Trailing == C2 && C2 + C3 < 32) {
14184 if (Leading == C2 && C2 + C3 < 32) {
14212 EVT VT =
N->getValueType(0);
14216 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14219 APInt SplatBits, SplatUndef;
14220 unsigned SplatBitSize;
14222 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14223 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14224 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14225 SplatBitSize == 64) {
14232 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14234 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14259 if (!Subtarget->hasV6Ops() ||
14260 (Subtarget->isThumb() &&
14261 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14264 SDValue SRL = OR->getOperand(0);
14265 SDValue SHL = OR->getOperand(1);
14268 SRL = OR->getOperand(1);
14269 SHL = OR->getOperand(0);
14276 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14280 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14281 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14282 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14301 unsigned Opcode = 0;
14302 if (
isS16(OpS16, DAG))
14303 Opcode = ARMISD::SMULWB;
14305 Opcode = ARMISD::SMULWT;
14320 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14323 EVT VT =
N->getValueType(0);
14338 if (VT != MVT::i32)
14351 if (Mask == 0xffff)
14358 if ((Val & ~Mask) != Val)
14364 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14383 (Mask == ~Mask2)) {
14386 if (Subtarget->hasDSP() &&
14387 (Mask == 0xffff || Mask == 0xffff0000))
14393 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14400 (~Mask == Mask2)) {
14403 if (Subtarget->hasDSP() &&
14404 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14460 if (
N->getOpcode() == ARMISD::VCMP)
14462 else if (
N->getOpcode() == ARMISD::VCMPZ)
14470 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14477 EVT VT =
N->getValueType(0);
14482 auto IsFreelyInvertable = [&](
SDValue V) {
14483 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14489 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14505 EVT VT =
N->getValueType(0);
14511 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14512 VT == MVT::v8i1 || VT == MVT::v16i1))
14515 APInt SplatBits, SplatUndef;
14516 unsigned SplatBitSize;
14518 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14519 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14520 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14521 SplatBitSize == 64) {
14528 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14530 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14557 unsigned SplatBitSize;
14560 APInt SplatBits0, SplatBits1;
14564 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14565 HasAnyUndefs) && !HasAnyUndefs) {
14566 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14567 HasAnyUndefs) && !HasAnyUndefs) {
14572 SplatBits0 == ~SplatBits1) {
14580 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14602 EVT VT =
N->getValueType(0);
14617 if (Subtarget->hasMVEIntegerOps()) {
14645 assert(
N->getOpcode() == ARMISD::BFI);
14648 ToMask =
~N->getConstantOperandAPInt(2);
14668 unsigned LastActiveBitInA =
A.countr_zero();
14669 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14670 return LastActiveBitInA - 1 == FirstActiveBitInB;
14675 APInt ToMask, FromMask;
14680 if (V.getOpcode() != ARMISD::BFI)
14683 APInt NewToMask, NewFromMask;
14685 if (NewFrom != From)
14689 if ((NewToMask & ToMask).getBoolValue())
14714 unsigned InvMask =
N->getConstantOperandVal(2);
14718 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14719 "undefined behavior");
14720 unsigned Mask = (1u << Width) - 1;
14722 if ((Mask & (~Mask2)) == 0)
14724 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14731 APInt ToMask1, FromMask1;
14734 APInt ToMask2, FromMask2;
14740 APInt NewFromMask = FromMask1 | FromMask2;
14741 APInt NewToMask = ToMask1 | ToMask2;
14743 EVT VT =
N->getValueType(0);
14746 if (NewFromMask[0] == 0)
14749 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
14757 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
14758 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14759 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14761 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14765 EVT VT =
N->getValueType(0);
14768 N->getOperand(1),
N->getOperand(2));
14780 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
14782 SDValue CSInc = Cmp->getOperand(0);
14792 if (CSInc.
getOpcode() == ARMISD::CSINC &&
14832 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
14833 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
14836 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
14838 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
14851 SDValue InDouble =
N->getOperand(0);
14852 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
14866 SDValue BasePtr = LD->getBasePtr();
14868 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
14869 LD->getAlign(), LD->getMemOperand()->getFlags());
14875 LD->getPointerInfo().getWithOffset(4),
14877 LD->getMemOperand()->getFlags());
14893 bool BVSwap = BV.
getOpcode() == ISD::BITCAST;
14896 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
14898 BVSwap = BV.
getOpcode() == ISD::BITCAST;
14910 if (!Subtarget->
isLittle() && BVSwap)
14928 if (!Subtarget->
isLittle() && BVSwap)
14947 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
14960 if (Op0->
getOpcode() == ARMISD::VMOVrh)
14971 if (Op0->
getOpcode() == ISD::BITCAST) {
14973 if (Copy.getValueType() == MVT::f32 &&
14975 bool HasGlue = Copy->getNumOperands() == 3;
14976 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
14977 HasGlue ? Copy->getOperand(2) :
SDValue()};
14978 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
14997 if (LN0->hasOneUse() && LN0->isUnindexed() &&
14998 LN0->getMemoryVT() == MVT::i16) {
15001 LN0->getBasePtr(), LN0->getMemOperand());
15019 EVT VT =
N->getValueType(0);
15053 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15054 for (
unsigned i = 0; i < NumElts; ++i) {
15055 SDNode *Elt =
N->getOperand(i).getNode();
15072 if (
N->getNumOperands() == 2)
15078 EVT VT =
N->getValueType(0);
15084 for (
unsigned i = 0; i < NumElts; ++i) {
15085 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(i));
15092 return DAG.
getNode(ISD::BITCAST, dl, VT, BV);
15110 EVT VT =
N->getValueType(0);
15118 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15122 if (
Use->getOpcode() != ISD::BITCAST ||
15123 Use->getValueType(0).isFloatingPoint())
15131 unsigned NumOfBitCastedElts = 0;
15133 unsigned NumOfRelevantElts = NumElts;
15134 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15136 if (Elt->
getOpcode() == ISD::BITCAST) {
15139 ++NumOfBitCastedElts;
15143 --NumOfRelevantElts;
15147 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15165 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15169 if (V.getOpcode() == ISD::BITCAST &&
15170 V->getOperand(0).getValueType() == MVT::i32)
15172 V = V.getOperand(0);
15181 Vec = DAG.
getNode(ISD::BITCAST, dl, VT, Vec);
15189 EVT VT =
N->getValueType(0);
15194 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15196 if (
Op->getOperand(0).getValueType() == VT)
15197 return Op->getOperand(0);
15198 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15205 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15212 if (
Op.getValueType() == MVT::i32) {
15223 EVT VT =
N->getValueType(0);
15228 if (ST->isLittle())
15229 return DAG.
getNode(ISD::BITCAST, dl, VT,
Op);
15232 if (
Op.getValueType() == VT)
15239 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15241 if (
Op->getOperand(0).getValueType() == VT)
15242 return Op->getOperand(0);
15243 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15251 if (!Subtarget->hasMVEIntegerOps())
15254 EVT VT =
N->getValueType(0);
15262 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15268 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15272 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15285 EVT VT =
N->getValueType(0);
15286 SDNode *Elt =
N->getOperand(1).getNode();
15295 SDValue Vec = DAG.
getNode(ISD::BITCAST, dl, FloatVT,
N->getOperand(0));
15296 SDValue V = DAG.
getNode(ISD::BITCAST, dl, MVT::f64,
N->getOperand(1));
15301 Vec, V,
N->getOperand(2));
15302 return DAG.
getNode(ISD::BITCAST, dl, VT, InsElt);
15311 EVT VT =
N->getValueType(0);
15339 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15340 isa<ConstantSDNode>(V->getOperand(1)) &&
15341 V->getConstantOperandVal(1) == Lane + 1 &&
15342 V->getOperand(0).getResNo() == ResNo;
15344 if (OtherIt == Op0->
users().
end())
15349 SDValue OtherExt(*OtherIt, 0);
15361 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15364 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15374 EVT VT =
N->getValueType(0);
15378 if (Op0->
getOpcode() == ARMISD::VDUP) {
15380 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15381 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15382 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15383 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15384 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15387 while (
X.getValueType() != VT &&
X->getOpcode() == ISD::BITCAST)
15388 X =
X->getOperand(0);
15389 if (
X.getValueType() == VT)
15397 return Op0.
getOperand(
N->getConstantOperandVal(1));
15407 unsigned Offset =
N->getConstantOperandVal(1);
15409 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15419 unsigned Idx =
N->getConstantOperandVal(1);
15433 EVT VT =
N->getValueType(0);
15436 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15438 Op.getOperand(0).getValueType().getScalarType())
15439 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15448 SDValue SubVec =
N->getOperand(1);
15449 uint64_t IdxVal =
N->getConstantOperandVal(2);
15460 if (IdxVal == 0 && Vec.
isUndef())
15466 (IdxVal != 0 && IdxVal != NumSubElts))
15497 ARMISD::VMOVN,
DL, VT,
15503 ARMISD::VMOVN,
DL, VT,
15539 EVT VT =
N->getValueType(0);
15550 unsigned HalfElts = NumElts/2;
15552 for (
unsigned n = 0; n < NumElts; ++n) {
15555 if (MaskElt < (
int)HalfElts)
15557 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15558 NewElt = HalfElts + MaskElt - NumElts;
15601 bool SimpleConstIncOnly,
15609 bool isLoadOp =
true;
15610 bool isLaneOp =
false;
15613 bool hasAlignment =
true;
15614 unsigned NewOpc = 0;
15615 unsigned NumVecs = 0;
15616 if (
Target.isIntrinsic) {
15617 unsigned IntNo =
N->getConstantOperandVal(1);
15621 case Intrinsic::arm_neon_vld1:
15625 case Intrinsic::arm_neon_vld2:
15629 case Intrinsic::arm_neon_vld3:
15633 case Intrinsic::arm_neon_vld4:
15637 case Intrinsic::arm_neon_vld1x2:
15640 hasAlignment =
false;
15642 case Intrinsic::arm_neon_vld1x3:
15645 hasAlignment =
false;
15647 case Intrinsic::arm_neon_vld1x4:
15650 hasAlignment =
false;
15652 case Intrinsic::arm_neon_vld2dup:
15656 case Intrinsic::arm_neon_vld3dup:
15660 case Intrinsic::arm_neon_vld4dup:
15664 case Intrinsic::arm_neon_vld2lane:
15669 case Intrinsic::arm_neon_vld3lane:
15674 case Intrinsic::arm_neon_vld4lane:
15679 case Intrinsic::arm_neon_vst1:
15684 case Intrinsic::arm_neon_vst2:
15685 NewOpc = ARMISD::VST2_UPD;
15689 case Intrinsic::arm_neon_vst3:
15694 case Intrinsic::arm_neon_vst4:
15695 NewOpc = ARMISD::VST4_UPD;
15699 case Intrinsic::arm_neon_vst2lane:
15705 case Intrinsic::arm_neon_vst3lane:
15711 case Intrinsic::arm_neon_vst4lane:
15717 case Intrinsic::arm_neon_vst1x2:
15721 hasAlignment =
false;
15723 case Intrinsic::arm_neon_vst1x3:
15727 hasAlignment =
false;
15729 case Intrinsic::arm_neon_vst1x4:
15733 hasAlignment =
false;
15738 switch (
N->getOpcode()) {
15774 VecTy =
N->getValueType(0);
15775 }
else if (
Target.isIntrinsic) {
15776 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
15779 "Node has to be a load, a store, or an intrinsic!");
15780 VecTy =
N->getOperand(1).getValueType();
15788 if (isLaneOp || isVLDDUPOp)
15791 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
15797 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
15806 EVT AlignedVecTy = VecTy;
15826 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
15827 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
15838 Alignment =
Align(1);
15844 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
15846 for (n = 0; n < NumResultVecs; ++n)
15847 Tys[n] = AlignedVecTy;
15848 Tys[n++] = MVT::i32;
15849 Tys[n] = MVT::Other;
15854 Ops.push_back(
N->getOperand(0));
15855 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
15860 Ops.push_back(StN->getValue());
15864 unsigned LastOperand =
15865 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
15866 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
15867 Ops.push_back(
N->getOperand(i));
15875 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::STORE) {
15877 StVal = DAG.
getNode(ISD::BITCAST, dl, AlignedVecTy, StVal);
15886 for (
unsigned i = 0; i < NumResultVecs; ++i)
15891 if (AlignedVecTy != VecTy &&
N->getOpcode() == ISD::LOAD) {
15892 SDValue &LdVal = NewResults[0];
15893 LdVal = DAG.
getNode(ISD::BITCAST, dl, VecTy, LdVal);
15928 switch (
N->getOpcode()) {
15932 *Ptr =
N->getOperand(0);
15933 *CInc =
N->getOperand(1);
15940 *Ptr =
N->getOperand(1);
15941 *CInc =
N->getOperand(2);
15960 const bool isStore =
N->getOpcode() == ISD::STORE;
15968 SDValue Addr =
N->getOperand(AddrOpIdx);
15979 unsigned ConstInc =
15984 if (BaseUpdates.
size() >= MaxBaseUpdates)
16004 unsigned UserOffset =
16007 if (!UserOffset || UserOffset <=
Offset)
16010 unsigned NewConstInc = UserOffset -
Offset;
16013 if (BaseUpdates.
size() >= MaxBaseUpdates)
16020 unsigned NumValidUpd = BaseUpdates.
size();
16021 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16032 return LHS.ConstInc <
RHS.ConstInc;
16061 unsigned IntNo =
N->getConstantOperandVal(1);
16062 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16064 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16087 bool isLoadOp =
true;
16088 unsigned NewOpc = 0;
16089 unsigned NumVecs = 0;
16093 case Intrinsic::arm_mve_vld2q:
16097 case Intrinsic::arm_mve_vld4q:
16101 case Intrinsic::arm_mve_vst2q:
16102 NewOpc = ARMISD::VST2_UPD;
16106 case Intrinsic::arm_mve_vst4q:
16107 NewOpc = ARMISD::VST4_UPD;
16116 VecTy =
N->getValueType(0);
16118 VecTy =
N->getOperand(3).getValueType();
16132 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16134 for (n = 0; n < NumResultVecs; ++n)
16136 Tys[n++] = MVT::i32;
16137 Tys[n] = MVT::Other;
16142 Ops.push_back(
N->getOperand(0));
16143 Ops.push_back(
N->getOperand(2));
16144 Ops.push_back(Inc);
16146 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16147 Ops.push_back(
N->getOperand(i));
16154 for (
unsigned i = 0; i < NumResultVecs; ++i)
16173 EVT VT =
N->getValueType(0);
16179 SDNode *VLD =
N->getOperand(0).getNode();
16182 unsigned NumVecs = 0;
16183 unsigned NewOpc = 0;
16185 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16188 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16191 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16203 if (
Use.getResNo() == NumVecs)
16206 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16207 VLDLaneNo !=
User->getConstantOperandVal(1))
16214 for (n = 0; n < NumVecs; ++n)
16216 Tys[n] = MVT::Other;
16226 unsigned ResNo =
Use.getResNo();
16228 if (ResNo == NumVecs)
16235 std::vector<SDValue> VLDDupResults;
16236 for (
unsigned n = 0; n < NumVecs; ++n)
16250 EVT VT =
N->getValueType(0);
16253 if (Subtarget->hasMVEIntegerOps()) {
16257 ExtractVT = MVT::i32;
16259 N->getOperand(0),
N->getOperand(1));
16270 while (
Op.getOpcode() == ISD::BITCAST)
16271 Op =
Op.getOperand(0);
16272 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16276 unsigned EltSize =
Op.getScalarValueSizeInBits();
16278 unsigned Imm =
Op.getConstantOperandVal(0);
16294 if (Subtarget->hasMVEIntegerOps()) {
16297 if (
Op.getValueType() == MVT::f32)
16298 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16299 DAG.
getNode(ISD::BITCAST, dl, MVT::i32,
Op));
16300 else if (
Op.getValueType() == MVT::f16)
16301 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16302 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16305 if (!Subtarget->hasNEON())
16312 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16313 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16314 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16319 LD->getMemoryVT(), LD->getMemOperand());
16330 EVT VT =
N->getValueType(0);
16352 assert(StVT != VT &&
"Cannot truncate to the same type");
16362 if (0 != (NumElems * FromEltSz) % ToEltSz)
16365 unsigned SizeRatio = FromEltSz / ToEltSz;
16370 NumElems * SizeRatio);
16376 for (
unsigned i = 0; i < NumElems; ++i)
16390 MVT StoreType = MVT::i8;
16392 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16412 for (
unsigned I = 0;
I <
E;
I++) {
16443 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16446 unsigned NumElements = 4;
16463 unsigned Off0 = Rev ? NumElts : 0;
16464 unsigned Off1 = Rev ? 0 : NumElts;
16466 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16467 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16469 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16477 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16497 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16508 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16512 NewToVT, Alignment, MMOFlags, AAInfo);
16545 unsigned NewOffset =
16553 NewToVT, Alignment, MMOFlags, AAInfo);
16575 {Extract.getOperand(0), Extract.getOperand(1)});
16606 if (Subtarget->hasNEON())
16610 if (Subtarget->hasMVEFloatOps())
16614 if (Subtarget->hasMVEIntegerOps()) {
16689 if (!Subtarget->hasNEON())
16693 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16701 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16703 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16704 uint32_t IntBits = IntTy.getSizeInBits();
16705 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16706 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16717 if (
C == -1 ||
C == 0 ||
C > 32)
16722 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16723 Intrinsic::arm_neon_vcvtfp2fxu;
16726 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16729 if (IntBits < FloatBits)
16737 if (!Subtarget->hasMVEFloatOps())
16745 EVT VT =
N->getValueType(0);
16750 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16751 if (
Op.getOpcode() != ISD::BITCAST ||
16752 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
16754 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16755 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16757 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16770 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
16781 EVT VT =
N->getValueType(0);
16784 if (!
N->getFlags().hasAllowReassociation())
16791 unsigned Opc =
A.getConstantOperandVal(0);
16792 if (
Opc != Intrinsic::arm_mve_vcmlaq)
16797 A.getOperand(3),
A.getOperand(4));
16829 if (!Subtarget->hasNEON())
16833 unsigned OpOpcode =
Op.getNode()->getOpcode();
16834 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
16838 SDValue ConstVec =
N->getOperand(1);
16842 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
16844 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
16845 uint32_t IntBits = IntTy.getSizeInBits();
16846 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16847 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16867 int32_t
C = IntVal.exactLogBase2();
16868 if (
C == -1 ||
C == 0 ||
C > 32)
16874 if (IntBits < FloatBits)
16876 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
16878 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
16879 : Intrinsic::arm_neon_vcvtfxu2fp;
16887 if (!ST->hasMVEIntegerOps())
16890 assert(
N->getOpcode() == ISD::VECREDUCE_ADD);
16891 EVT ResVT =
N->getValueType(0);
16919 EVT AVT =
A.getValueType();
16925 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
16926 EVT AVT =
A.getValueType();
16934 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
16935 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
16938 if (ExtTypeMatches(
A, ExtTypes))
16939 return ExtendIfNeeded(
A, ExtendCode);
16942 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
16952 if (ExtTypeMatches(
A, ExtTypes))
16953 return ExtendIfNeeded(
A, ExtendCode);
16956 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
16966 if (ResVT != RetTy)
16969 if (
Mul->getOpcode() == ExtendCode &&
16970 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
16972 Mul =
Mul->getOperand(0);
16981 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
16982 A = ExtendIfNeeded(
A, ExtendCode);
16983 B = ExtendIfNeeded(
B, ExtendCode);
16988 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17001 if (
Mul->getOpcode() == ExtendCode &&
17002 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17004 Mul =
Mul->getOperand(0);
17013 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17014 A = ExtendIfNeeded(
A, ExtendCode);
17015 B = ExtendIfNeeded(
B, ExtendCode);
17026 EVT VT =
Ops[0].getValueType();
17027 if (VT == MVT::v16i8) {
17028 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17029 "Unexpected illegal long reduction opcode");
17030 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17042 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17055 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17057 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17058 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17060 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17061 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17063 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17066 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17069 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17073 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17076 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17079 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17082 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17085 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17088 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17091 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17093 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17095 return Create64bitNode(ARMISD::VADDLVs, {
A});
17097 return Create64bitNode(ARMISD::VADDLVu, {
A});
17100 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17103 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17106 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17108 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17110 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17112 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17115 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17118 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17125 Op =
Op->getOperand(1);
17127 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17129 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17135 return DAG.
getNode(ISD::VECREDUCE_ADD, dl, ResVT, Ext);
17146 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17148 if (!Shuf || !Shuf->getOperand(1).isUndef())
17153 APInt SetElts(Mask.size(), 0);
17154 for (
int E : Mask) {
17162 if (
N->getNumOperands() != VecOp + 1) {
17164 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17170 if (
Op.getValueType().isVector())
17171 Ops.push_back(
Op.getOperand(0));
17182 unsigned IsTop =
N->getConstantOperandVal(2);
17189 if (Op0->
isUndef() && !IsTop)
17194 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17195 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17203 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17205 APInt Op0DemandedElts =
17206 IsTop ? Op1DemandedElts
17221 unsigned IsTop =
N->getConstantOperandVal(2);
17223 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17224 APInt Op0DemandedElts =
17236 EVT VT =
N->getValueType(0);
17243 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17244 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17248 LHS.getOperand(0),
RHS.getOperand(0));
17263 int ShiftAmt =
C->getSExtValue();
17264 if (ShiftAmt == 0) {
17270 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17271 unsigned NewOpcode =
17272 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17287 unsigned IntNo =
N->getConstantOperandVal(0);
17298 case Intrinsic::arm_neon_vshifts:
17299 case Intrinsic::arm_neon_vshiftu:
17300 case Intrinsic::arm_neon_vrshifts:
17301 case Intrinsic::arm_neon_vrshiftu:
17302 case Intrinsic::arm_neon_vrshiftn:
17303 case Intrinsic::arm_neon_vqshifts:
17304 case Intrinsic::arm_neon_vqshiftu:
17305 case Intrinsic::arm_neon_vqshiftsu:
17306 case Intrinsic::arm_neon_vqshiftns:
17307 case Intrinsic::arm_neon_vqshiftnu:
17308 case Intrinsic::arm_neon_vqshiftnsu:
17309 case Intrinsic::arm_neon_vqrshiftns:
17310 case Intrinsic::arm_neon_vqrshiftnu:
17311 case Intrinsic::arm_neon_vqrshiftnsu: {
17312 EVT VT =
N->getOperand(1).getValueType();
17314 unsigned VShiftOpc = 0;
17317 case Intrinsic::arm_neon_vshifts:
17318 case Intrinsic::arm_neon_vshiftu:
17320 VShiftOpc = ARMISD::VSHLIMM;
17323 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17324 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17325 : ARMISD::VSHRuIMM);
17330 case Intrinsic::arm_neon_vrshifts:
17331 case Intrinsic::arm_neon_vrshiftu:
17336 case Intrinsic::arm_neon_vqshifts:
17337 case Intrinsic::arm_neon_vqshiftu:
17342 case Intrinsic::arm_neon_vqshiftsu:
17347 case Intrinsic::arm_neon_vrshiftn:
17348 case Intrinsic::arm_neon_vqshiftns:
17349 case Intrinsic::arm_neon_vqshiftnu:
17350 case Intrinsic::arm_neon_vqshiftnsu:
17351 case Intrinsic::arm_neon_vqrshiftns:
17352 case Intrinsic::arm_neon_vqrshiftnu:
17353 case Intrinsic::arm_neon_vqrshiftnsu:
17365 case Intrinsic::arm_neon_vshifts:
17366 case Intrinsic::arm_neon_vshiftu:
17369 case Intrinsic::arm_neon_vrshifts:
17370 VShiftOpc = ARMISD::VRSHRsIMM;
17372 case Intrinsic::arm_neon_vrshiftu:
17373 VShiftOpc = ARMISD::VRSHRuIMM;
17375 case Intrinsic::arm_neon_vrshiftn:
17376 VShiftOpc = ARMISD::VRSHRNIMM;
17378 case Intrinsic::arm_neon_vqshifts:
17379 VShiftOpc = ARMISD::VQSHLsIMM;
17381 case Intrinsic::arm_neon_vqshiftu:
17382 VShiftOpc = ARMISD::VQSHLuIMM;
17384 case Intrinsic::arm_neon_vqshiftsu:
17385 VShiftOpc = ARMISD::VQSHLsuIMM;
17387 case Intrinsic::arm_neon_vqshiftns:
17388 VShiftOpc = ARMISD::VQSHRNsIMM;
17390 case Intrinsic::arm_neon_vqshiftnu:
17391 VShiftOpc = ARMISD::VQSHRNuIMM;
17393 case Intrinsic::arm_neon_vqshiftnsu:
17394 VShiftOpc = ARMISD::VQSHRNsuIMM;
17396 case Intrinsic::arm_neon_vqrshiftns:
17397 VShiftOpc = ARMISD::VQRSHRNsIMM;
17399 case Intrinsic::arm_neon_vqrshiftnu:
17400 VShiftOpc = ARMISD::VQRSHRNuIMM;
17402 case Intrinsic::arm_neon_vqrshiftnsu:
17403 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17408 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17409 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17412 case Intrinsic::arm_neon_vshiftins: {
17413 EVT VT =
N->getOperand(1).getValueType();
17415 unsigned VShiftOpc = 0;
17418 VShiftOpc = ARMISD::VSLIIMM;
17419 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17420 VShiftOpc = ARMISD::VSRIIMM;
17426 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17427 N->getOperand(1),
N->getOperand(2),
17431 case Intrinsic::arm_neon_vqrshifts:
17432 case Intrinsic::arm_neon_vqrshiftu:
17436 case Intrinsic::arm_neon_vbsl: {
17438 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17439 N->getOperand(2),
N->getOperand(3));
17441 case Intrinsic::arm_mve_vqdmlah:
17442 case Intrinsic::arm_mve_vqdmlash:
17443 case Intrinsic::arm_mve_vqrdmlah:
17444 case Intrinsic::arm_mve_vqrdmlash:
17445 case Intrinsic::arm_mve_vmla_n_predicated:
17446 case Intrinsic::arm_mve_vmlas_n_predicated:
17447 case Intrinsic::arm_mve_vqdmlah_predicated:
17448 case Intrinsic::arm_mve_vqdmlash_predicated:
17449 case Intrinsic::arm_mve_vqrdmlah_predicated:
17450 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17455 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17462 case Intrinsic::arm_mve_minv:
17463 case Intrinsic::arm_mve_maxv:
17464 case Intrinsic::arm_mve_minav:
17465 case Intrinsic::arm_mve_maxav:
17466 case Intrinsic::arm_mve_minv_predicated:
17467 case Intrinsic::arm_mve_maxv_predicated:
17468 case Intrinsic::arm_mve_minav_predicated:
17469 case Intrinsic::arm_mve_maxav_predicated: {
17472 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17479 case Intrinsic::arm_mve_addv: {
17482 bool Unsigned =
N->getConstantOperandVal(2);
17483 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17487 case Intrinsic::arm_mve_addlv:
17488 case Intrinsic::arm_mve_addlv_predicated: {
17491 bool Unsigned =
N->getConstantOperandVal(2);
17492 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17493 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17494 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17497 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17499 Ops.push_back(
N->getOperand(i));
17520 EVT VT =
N->getValueType(0);
17522 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17523 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17524 N->getOperand(0)->hasOneUse()) {
17541 if (AndMask == 255 || AndMask == 65535)
17545 if (MaskedBits > ShiftAmt) {
17560 if (ST->hasMVEIntegerOps())
17565 switch (
N->getOpcode()) {
17571 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17578 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17579 unsigned VShiftOpc =
17580 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17582 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17598 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17601 EVT FromVT = LD->getValueType(0);
17602 EVT ToVT =
N->getValueType(0);
17609 unsigned NumElements = 0;
17610 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17612 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17614 if (NumElements == 0 ||
17624 SDValue BasePtr = LD->getBasePtr();
17625 Align Alignment = LD->getBaseAlign();
17646 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17647 Alignment, MMOFlags, AAInfo);
17653 if (FromEltVT == MVT::f16) {
17656 for (
unsigned i = 0; i < Loads.
size(); i++) {
17658 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
17682 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17686 EVT VT =
N->getValueType(0);
17690 if (VT == MVT::i32 &&
17691 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17696 switch (
N->getOpcode()) {
17699 Opc = ARMISD::VGETLANEs;
17703 Opc = ARMISD::VGETLANEu;
17710 if (ST->hasMVEIntegerOps())
17719 if (ST->hasMVEFloatOps())
17730 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17734 EVT VT =
Op.getValueType();
17737 if (VT != MVT::i32 ||
17750 APInt MaxC = Max.getConstantOperandAPInt(1);
17753 !(MinC + 1).isPowerOf2())
17771 EVT VT =
N->getValueType(0);
17774 if (VT == MVT::i32)
17777 if (!ST->hasMVEIntegerOps())
17783 if (VT != MVT::v4i32 && VT != MVT::v8i16)
17786 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
17794 if (VT == MVT::v4i32)
17795 SaturateC =
APInt(32, (1 << 15) - 1,
true);
17797 SaturateC =
APInt(16, (1 << 7) - 1,
true);
17804 MaxC != ~SaturateC)
17809 if (IsSignedSaturate(
N, N0.
getNode())) {
17812 if (VT == MVT::v4i32) {
17813 HalfVT = MVT::v8i16;
17814 ExtVT = MVT::v4i16;
17816 HalfVT = MVT::v16i8;
17831 auto IsUnsignedSaturate = [&](
SDNode *Min) {
17837 if (VT == MVT::v4i32)
17838 SaturateC =
APInt(32, (1 << 16) - 1,
true);
17840 SaturateC =
APInt(16, (1 << 8) - 1,
true);
17849 if (IsUnsignedSaturate(
N)) {
17853 if (VT == MVT::v4i32) {
17854 HalfVT = MVT::v8i16;
17855 ExtConst = 0x0000FFFF;
17857 HalfVT = MVT::v16i8;
17879 const APInt *CV = &
C->getAPIntValue();
17897 SDValue Op0 = CMOV->getOperand(0);
17898 SDValue Op1 = CMOV->getOperand(1);
17899 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
17900 SDValue CmpZ = CMOV->getOperand(3);
17936 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
17943 if ((OrCI & Known.
Zero) != OrCI)
17949 EVT VT =
X.getValueType();
17950 unsigned BitInX = AndC->
logBase2();
17958 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
17959 BitInY < NumActiveBits; ++BitInY) {
17960 if (OrCI[BitInY] == 0)
17963 Mask.setBit(BitInY);
17964 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
17980 switch (
N->getOpcode()) {
17995 if (Const->isZero())
17997 else if (Const->isOne())
18005 unsigned IntOp =
N.getConstantOperandVal(1);
18006 if (IntOp != Intrinsic::test_start_loop_iterations &&
18007 IntOp != Intrinsic::loop_decrement_reg)
18033 bool Negate =
false;
18037 if (
N->getOpcode() == ISD::BRCOND) {
18039 Cond =
N->getOperand(1);
18040 Dest =
N->getOperand(2);
18042 assert(
N->getOpcode() == ISD::BR_CC &&
"Expected BRCOND or BR_CC!");
18044 Cond =
N->getOperand(2);
18045 Dest =
N->getOperand(4);
18047 if (!Const->isOne() && !Const->isZero())
18049 Imm = Const->getZExtValue();
18077 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18078 "unsupported condition");
18083 unsigned IntOp =
Int->getConstantOperandVal(1);
18084 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() == ISD::BR) &&
18085 "expected single br user");
18086 SDNode *Br = *
N->user_begin();
18096 if (IntOp == Intrinsic::test_start_loop_iterations) {
18098 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18100 if (IsTrueIfZero(CC, Imm)) {
18102 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18106 UpdateUncondBr(Br, Dest, DAG);
18108 SDValue Ops[] = {Chain, Setup, OtherTarget};
18109 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18121 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18125 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18129 if (
Target == OtherTarget)
18130 UpdateUncondBr(Br, Dest, DAG);
18136 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18145 if (Cmp.getOpcode() != ARMISD::CMPZ)
18150 SDValue LHS = Cmp.getOperand(0);
18151 SDValue RHS = Cmp.getOperand(1);
18160 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18161 LHS->getOperand(0)->hasOneUse() &&
18165 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18177 if (Cmp.getOpcode() != ARMISD::CMPZ)
18181 EVT VT =
N->getValueType(0);
18183 SDValue LHS = Cmp.getOperand(0);
18184 SDValue RHS = Cmp.getOperand(1);
18185 SDValue FalseVal =
N->getOperand(0);
18186 SDValue TrueVal =
N->getOperand(1);
18191 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18215 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18216 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18217 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18220 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18225 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18228 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18229 LHS->getOperand(2), LHS->getOperand(3));
18239 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18243 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18245 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18254 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18287 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18299 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18319 const APInt *TrueConst;
18320 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18321 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18322 FalseVal.getOperand(1) == RHS) ||
18326 unsigned ShiftAmount = TrueConst->
logBase2();
18341 if (Known.
Zero == 0xfffffffe)
18344 else if (Known.
Zero == 0xffffff00)
18347 else if (Known.
Zero == 0xffff0000)
18360 EVT DstVT =
N->getValueType(0);
18363 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18364 EVT SrcVT = Src.getValueType();
18366 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18371 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18372 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18373 Src.getValueType().getScalarSizeInBits())
18374 Src = Src.getOperand(0);
18378 EVT SrcVT = Src.getValueType();
18379 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18380 Src.getOpcode() == ARMISD::VMVNIMM ||
18381 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18384 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18398 EVT VT =
N->getValueType(0);
18406 if (
N->getNumOperands() == 2 &&
18410 N->getOperand(0).getOperand(1),
18411 N->getOperand(1).getOperand(0),
18412 N->getOperand(1).getOperand(1));
18415 if (
N->getNumOperands() == 2 &&
18421 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18422 S0->getOperand(1) ==
S1->getOperand(1)) {
18425 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18429 ARMISD::VMOVN,
DL, VT,
18430 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18431 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18435 ARMISD::VMOVN,
DL, VT,
18436 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18437 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18445 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18446 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18447 (Op.getOpcode() == ISD::BITCAST &&
18448 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18451 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18453 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18471 int NumIns =
N->getNumOperands();
18472 assert((NumIns == 2 || NumIns == 4) &&
18473 "Expected 2 or 4 inputs to an MVETrunc");
18475 if (
N->getNumOperands() == 4)
18479 for (
int I = 0;
I < NumIns;
I++) {
18481 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18486 Ptr, MPI, StoreVT,
Align(4));
18501 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18504 EVT FromVT = LD->getMemoryVT();
18505 EVT ToVT =
N->getValueType(0);
18512 unsigned NumElements = 0;
18513 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18515 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18517 assert(NumElements != 0);
18523 LD->getExtensionType() != NewExtType)
18530 SDValue BasePtr = LD->getBasePtr();
18531 Align Alignment = LD->getBaseAlign();
18550 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18551 Alignment, MMOFlags, AAInfo);
18567 EVT VT =
N->getValueType(0);
18569 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18570 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18572 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18574 auto Extend = [&](
SDValue V) {
18583 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
18584 SDValue Ext = Extend(
N->getOperand(0));
18592 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18593 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
18597 auto CheckInregMask = [&](
int Start,
int Offset) {
18599 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18605 if (CheckInregMask(0, 0))
18607 else if (CheckInregMask(0, 1))
18608 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18609 else if (CheckInregMask(0, Mask.size()))
18611 else if (CheckInregMask(0, Mask.size() + 1))
18612 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18617 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18621 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18628 if (
N->getOperand(0)->getOpcode() == ISD::LOAD)
18639 int NumOuts =
N->getNumValues();
18640 assert((NumOuts == 2 || NumOuts == 4) &&
18641 "Expected 2 or 4 outputs to an MVEEXT");
18642 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18644 if (
N->getNumOperands() == 4)
18650 StackPtr, MPI,
Align(4));
18653 for (
int I = 0;
I < NumOuts;
I++) {
18655 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18656 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18661 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
18670 switch (
N->getOpcode()) {
18721 case ISD::FP_EXTEND:
18730 case ARMISD::BRCOND:
18734 case ARMISD::CSINC:
18735 case ARMISD::CSINV:
18736 case ARMISD::CSNEG:
18749 case ARMISD::PREDICATE_CAST:
18751 case ARMISD::VECTOR_REG_CAST:
18760 case ISD::VECREDUCE_ADD:
18762 case ARMISD::VADDVs:
18763 case ARMISD::VADDVu:
18764 case ARMISD::VADDLVs:
18765 case ARMISD::VADDLVu:
18766 case ARMISD::VADDLVAs:
18767 case ARMISD::VADDLVAu:
18768 case ARMISD::VMLAVs:
18769 case ARMISD::VMLAVu:
18770 case ARMISD::VMLALVs:
18771 case ARMISD::VMLALVu:
18772 case ARMISD::VMLALVAs:
18773 case ARMISD::VMLALVAu:
18775 case ARMISD::VMOVN:
18777 case ARMISD::VQMOVNs:
18778 case ARMISD::VQMOVNu:
18780 case ARMISD::VQDMULH:
18786 case ARMISD::SMULWB: {
18787 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18793 case ARMISD::SMULWT: {
18794 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18800 case ARMISD::SMLALBB:
18801 case ARMISD::QADD16b:
18802 case ARMISD::QSUB16b:
18803 case ARMISD::UQADD16b:
18804 case ARMISD::UQSUB16b: {
18805 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18812 case ARMISD::SMLALBT: {
18813 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
18815 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
18822 case ARMISD::SMLALTB: {
18823 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
18825 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
18832 case ARMISD::SMLALTT: {
18833 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18840 case ARMISD::QADD8b:
18841 case ARMISD::QSUB8b:
18842 case ARMISD::UQADD8b:
18843 case ARMISD::UQSUB8b: {
18844 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18852 if (
N->getOperand(1) ==
N->getOperand(2))
18853 return N->getOperand(1);
18857 switch (
N->getConstantOperandVal(1)) {
18858 case Intrinsic::arm_neon_vld1:
18859 case Intrinsic::arm_neon_vld1x2:
18860 case Intrinsic::arm_neon_vld1x3:
18861 case Intrinsic::arm_neon_vld1x4:
18862 case Intrinsic::arm_neon_vld2:
18863 case Intrinsic::arm_neon_vld3:
18864 case Intrinsic::arm_neon_vld4:
18865 case Intrinsic::arm_neon_vld2lane:
18866 case Intrinsic::arm_neon_vld3lane:
18867 case Intrinsic::arm_neon_vld4lane:
18868 case Intrinsic::arm_neon_vld2dup:
18869 case Intrinsic::arm_neon_vld3dup:
18870 case Intrinsic::arm_neon_vld4dup:
18871 case Intrinsic::arm_neon_vst1:
18872 case Intrinsic::arm_neon_vst1x2:
18873 case Intrinsic::arm_neon_vst1x3:
18874 case Intrinsic::arm_neon_vst1x4:
18875 case Intrinsic::arm_neon_vst2:
18876 case Intrinsic::arm_neon_vst3:
18877 case Intrinsic::arm_neon_vst4:
18878 case Intrinsic::arm_neon_vst2lane:
18879 case Intrinsic::arm_neon_vst3lane:
18880 case Intrinsic::arm_neon_vst4lane:
18882 case Intrinsic::arm_mve_vld2q:
18883 case Intrinsic::arm_mve_vld4q:
18884 case Intrinsic::arm_mve_vst2q:
18885 case Intrinsic::arm_mve_vst4q:
18896 return (VT == MVT::f32) && (
Opc == ISD::LOAD ||
Opc == ISD::STORE);
18902 unsigned *
Fast)
const {
18908 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
18911 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
18913 if (AllowsUnaligned) {
18915 *
Fast = Subtarget->hasV7Ops();
18920 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
18924 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
18931 if (!Subtarget->hasMVEIntegerOps())
18935 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
18936 Ty == MVT::v2i1)) {
18944 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
18960 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
18961 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
18962 Ty == MVT::v2f64) {
18973 const AttributeList &FuncAttributes)
const {
18975 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
18976 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
18978 if (
Op.size() >= 16 &&
18984 }
else if (
Op.size() >= 8 &&
19001 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19003 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19005 return (SrcBits == 64 && DestBits == 32);
19014 return (SrcBits == 64 && DestBits == 32);
19050 return Subtarget->hasFullFP16();
19057 if (!Subtarget->hasMVEIntegerOps())
19076 if (Ld->isExpandingLoad())
19080 if (Subtarget->hasMVEIntegerOps())
19093 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19125bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19127 if (Subtarget->useSoftFloat())
19136 return Subtarget->hasMVEFloatOps();
19154 unsigned Scale = 1;
19171 if ((V & (Scale - 1)) != 0)
19180 if (VT.
isVector() && Subtarget->hasNEON())
19183 !Subtarget->hasMVEFloatOps())
19186 bool IsNeg =
false;
19192 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19195 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19211 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19217 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19247 default:
return false;
19266 int Scale = AM.
Scale;
19271 default:
return false;
19279 Scale = Scale & ~1;
19280 return Scale == 2 || Scale == 4 || Scale == 8;
19297 if (Scale & 1)
return false;
19304 const int Scale = AM.
Scale;
19314 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19330 switch (AM.
Scale) {
19341 if (Subtarget->isThumb1Only())
19344 if (Subtarget->isThumb2())
19347 int Scale = AM.
Scale;
19349 default:
return false;
19353 if (Scale < 0) Scale = -Scale;
19361 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19374 if (Scale & 1)
return false;
19387 if (!Subtarget->isThumb())
19390 if (Subtarget->isThumb2())
19394 return Imm >= 0 && Imm <= 255;
19404 if (!Subtarget->isThumb())
19406 if (Subtarget->isThumb2())
19409 return AbsImm <= 255;
19444 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19448 int RHSC = (int)
RHS->getZExtValue();
19449 if (RHSC < 0 && RHSC > -256) {
19459 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19462 int RHSC = (int)
RHS->getZExtValue();
19463 if (RHSC < 0 && RHSC > -0x1000) {
19505 int RHSC = (int)
RHS->getZExtValue();
19506 if (RHSC < 0 && RHSC > -0x100) {
19511 }
else if (RHSC > 0 && RHSC < 0x100) {
19522 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19533 bool CanChangeType = isLE && !IsMasked;
19536 int RHSC = (int)
RHS->getZExtValue();
19538 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19539 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19544 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19555 if (VT == MVT::v4i16) {
19556 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19558 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19559 if (IsInRange(RHSC, 0x80, 1))
19561 }
else if (Alignment >= 4 &&
19562 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19563 IsInRange(RHSC, 0x80, 4))
19565 else if (Alignment >= 2 &&
19566 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19567 IsInRange(RHSC, 0x80, 2))
19569 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19582 if (Subtarget->isThumb1Only())
19588 bool isSEXTLoad =
false;
19589 bool IsMasked =
false;
19591 Ptr = LD->getBasePtr();
19592 VT = LD->getMemoryVT();
19593 Alignment = LD->getAlign();
19596 Ptr = ST->getBasePtr();
19597 VT = ST->getMemoryVT();
19598 Alignment = ST->getAlign();
19600 Ptr = LD->getBasePtr();
19601 VT = LD->getMemoryVT();
19602 Alignment = LD->getAlign();
19606 Ptr = ST->getBasePtr();
19607 VT = ST->getMemoryVT();
19608 Alignment = ST->getAlign();
19614 bool isLegal =
false;
19616 isLegal = Subtarget->hasMVEIntegerOps() &&
19618 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19619 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19621 if (Subtarget->isThumb2())
19646 bool isSEXTLoad =
false, isNonExt;
19647 bool IsMasked =
false;
19649 VT = LD->getMemoryVT();
19650 Ptr = LD->getBasePtr();
19651 Alignment = LD->getAlign();
19655 VT = ST->getMemoryVT();
19656 Ptr = ST->getBasePtr();
19657 Alignment = ST->getAlign();
19658 isNonExt = !ST->isTruncatingStore();
19660 VT = LD->getMemoryVT();
19661 Ptr = LD->getBasePtr();
19662 Alignment = LD->getAlign();
19667 VT = ST->getMemoryVT();
19668 Ptr = ST->getBasePtr();
19669 Alignment = ST->getAlign();
19670 isNonExt = !ST->isTruncatingStore();
19675 if (Subtarget->isThumb1Only()) {
19678 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19679 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19682 if (!RHS || RHS->getZExtValue() != 4)
19684 if (Alignment <
Align(4))
19688 Base =
Op->getOperand(0);
19694 bool isLegal =
false;
19696 isLegal = Subtarget->hasMVEIntegerOps() &&
19701 if (Subtarget->isThumb2())
19715 !Subtarget->isThumb2())
19729 const APInt &DemandedElts,
19731 unsigned Depth)
const {
19734 switch (
Op.getOpcode()) {
19741 if (
Op.getResNo() == 0) {
19752 case ARMISD::CMOV: {
19767 case Intrinsic::arm_ldaex:
19768 case Intrinsic::arm_ldrex: {
19776 case ARMISD::BFI: {
19783 const APInt &Mask =
Op.getConstantOperandAPInt(2);
19784 Known.
Zero &= Mask;
19788 case ARMISD::VGETLANEs:
19789 case ARMISD::VGETLANEu: {
19790 const SDValue &SrcSV =
Op.getOperand(0);
19796 "VGETLANE index out of bounds");
19801 EVT VT =
Op.getValueType();
19807 if (
Op.getOpcode() == ARMISD::VGETLANEs)
19808 Known = Known.
sext(DstSz);
19810 Known = Known.
zext(DstSz);
19815 case ARMISD::VMOVrh: {
19818 Known = KnownOp.
zext(32);
19821 case ARMISD::CSINC:
19822 case ARMISD::CSINV:
19823 case ARMISD::CSNEG: {
19831 if (
Op.getOpcode() == ARMISD::CSINC)
19834 else if (
Op.getOpcode() == ARMISD::CSINV)
19836 else if (
Op.getOpcode() == ARMISD::CSNEG)
19843 case ARMISD::VORRIMM:
19844 case ARMISD::VBICIMM: {
19845 unsigned Encoded =
Op.getConstantOperandVal(1);
19846 unsigned DecEltBits = 0;
19849 unsigned EltBits =
Op.getScalarValueSizeInBits();
19850 if (EltBits != DecEltBits) {
19859 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
19860 APInt Imm(DecEltBits, DecodedVal);
19862 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
19863 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
19881 EVT VT =
Op.getValueType();
19887 assert(VT == MVT::i32 &&
"Unexpected integer type");
19894 unsigned Mask =
C->getZExtValue();
19897 unsigned ShrunkMask = Mask & Demanded;
19898 unsigned ExpandedMask = Mask | ~Demanded;
19902 if (ShrunkMask == 0)
19908 if (ExpandedMask == ~0U)
19911 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
19912 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
19914 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
19915 if (NewMask == Mask)
19924 if (IsLegalMask(0xFF))
19925 return UseMask(0xFF);
19928 if (IsLegalMask(0xFFFF))
19929 return UseMask(0xFFFF);
19933 if (ShrunkMask < 256)
19934 return UseMask(ShrunkMask);
19938 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
19939 return UseMask(ExpandedMask);
19954 unsigned Depth)
const {
19955 unsigned Opc =
Op.getOpcode();
19959 case ARMISD::LSRL: {
19963 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
19965 unsigned ShAmt =
Op->getConstantOperandVal(2);
19975 case ARMISD::VBICIMM: {
19977 unsigned ModImm =
Op.getConstantOperandVal(1);
19978 unsigned EltBits = 0;
19980 if ((OriginalDemandedBits & Mask) == 0)
19986 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20001 if (!Subtarget->hasVFP2Base())
20005 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20017 unsigned S = Constraint.
size();
20019 switch (Constraint[0]) {
20031 }
else if (S == 2) {
20032 switch (Constraint[0]) {
20049 Value *CallOperandVal =
info.CallOperandVal;
20052 if (!CallOperandVal)
20056 switch (*constraint) {
20062 if (Subtarget->isThumb())
20077 if (PR == 0 || VT == MVT::Other)
20079 if (ARM::SPRRegClass.
contains(PR))
20080 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20081 if (ARM::DPRRegClass.
contains(PR))
20086using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20090 switch (Constraint.
size()) {
20093 switch (Constraint[0]) {
20095 if (Subtarget->isThumb())
20096 return RCPair(0U, &ARM::tGPRRegClass);
20097 return RCPair(0U, &ARM::GPRRegClass);
20099 if (Subtarget->isThumb())
20100 return RCPair(0U, &ARM::hGPRRegClass);
20103 if (Subtarget->isThumb1Only())
20104 return RCPair(0U, &ARM::tGPRRegClass);
20105 return RCPair(0U, &ARM::GPRRegClass);
20107 if (VT == MVT::Other)
20109 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20110 return RCPair(0U, &ARM::SPRRegClass);
20112 return RCPair(0U, &ARM::DPRRegClass);
20114 return RCPair(0U, &ARM::QPRRegClass);
20117 if (VT == MVT::Other)
20119 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20120 return RCPair(0U, &ARM::SPR_8RegClass);
20122 return RCPair(0U, &ARM::DPR_8RegClass);
20124 return RCPair(0U, &ARM::QPR_8RegClass);
20127 if (VT == MVT::Other)
20129 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20130 return RCPair(0U, &ARM::SPRRegClass);
20132 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20134 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20140 if (Constraint[0] ==
'T') {
20141 switch (Constraint[1]) {
20145 return RCPair(0U, &ARM::tGPREvenRegClass);
20147 return RCPair(0U, &ARM::tGPROddRegClass);
20156 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20157 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20161 return {0,
nullptr};
20169 std::vector<SDValue> &
Ops,
20174 if (Constraint.
size() != 1)
20177 char ConstraintLetter = Constraint[0];
20178 switch (ConstraintLetter) {
20181 case 'I':
case 'J':
case 'K':
case 'L':
20182 case 'M':
case 'N':
case 'O':
20187 int64_t CVal64 =
C->getSExtValue();
20188 int CVal = (int) CVal64;
20191 if (CVal != CVal64)
20194 switch (ConstraintLetter) {
20198 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20199 if (CVal >= 0 && CVal <= 65535)
20203 if (Subtarget->isThumb1Only()) {
20206 if (CVal >= 0 && CVal <= 255)
20208 }
else if (Subtarget->isThumb2()) {
20222 if (Subtarget->isThumb1Only()) {
20227 if (CVal >= -255 && CVal <= -1)
20233 if (CVal >= -4095 && CVal <= 4095)
20239 if (Subtarget->isThumb1Only()) {
20246 }
else if (Subtarget->isThumb2()) {
20266 if (Subtarget->isThumb1Only()) {
20269 if (CVal >= -7 && CVal < 7)
20271 }
else if (Subtarget->isThumb2()) {
20291 if (Subtarget->isThumb1Only()) {
20294 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20300 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20306 if (Subtarget->isThumb1Only()) {
20308 if (CVal >= 0 && CVal <= 31)
20314 if (Subtarget->isThumb1Only()) {
20317 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20326 if (Result.getNode()) {
20327 Ops.push_back(Result);
20337 "Unhandled Opcode in getDivRemLibcall");
20343 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20344 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20345 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20346 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20355 "Unhandled Opcode in getDivRemArgList");
20359 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20360 EVT ArgVT =
N->getOperand(i).getValueType();
20365 Args.push_back(Entry);
20373 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20374 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20375 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20376 "Register-based DivRem lowering only");
20377 unsigned Opcode =
Op->getOpcode();
20379 "Invalid opcode for Div/Rem lowering");
20381 EVT VT =
Op->getValueType(0);
20403 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20404 : Subtarget->hasDivideInARMMode();
20405 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20406 Op->getSimpleValueType(0) == MVT::i32) {
20408 const SDValue Dividend =
Op->getOperand(0);
20409 const SDValue Divisor =
Op->getOperand(1);
20410 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20414 SDValue Values[2] = {Div, Rem};
20431 if (Subtarget->isTargetWindows())
20434 TargetLowering::CallLoweringInfo CLI(DAG);
20439 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20440 return CallInfo.first;
20446 EVT VT =
N->getValueType(0);
20452 Result[0], Result[1]);
20456 std::vector<Type*> RetTyParams;
20457 Type *RetTyElement;
20467 RetTyParams.push_back(RetTyElement);
20468 RetTyParams.push_back(RetTyElement);
20481 if (Subtarget->isTargetWindows())
20489 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20492 SDNode *ResNode = CallResult.first.getNode();
20499 assert(Subtarget->isTargetWindows() &&
"unsupported target platform");
20507 "no-stack-arg-probe")) {
20511 Chain =
SP.getValue(1);
20528 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20529 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
20539 bool IsStrict =
Op->isStrictFPOpcode();
20540 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20541 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20543 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20544 "Unexpected type for custom-lowering FP_EXTEND");
20546 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20547 "With both FP DP and 16, any FP conversion is legal!");
20549 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20550 "With FP16, 16 to 32 conversion is legal!");
20553 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20558 Loc,
Op.getValueType(), SrcVal);
20573 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20574 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20575 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20576 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20580 {DstVT, MVT::Other}, {Chain, SrcVal});
20583 SrcVal = DAG.
getNode(ISD::FP_EXTEND, Loc, DstVT, SrcVal);
20587 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20588 "Unexpected type for custom-lowering FP_EXTEND");
20589 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20594 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20598 bool IsStrict =
Op->isStrictFPOpcode();
20600 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20602 EVT DstVT =
Op.getValueType();
20603 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20606 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20607 "Unexpected type for custom-lowering FP_ROUND");
20609 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20610 "With both FP DP and 16, any FP conversion is legal!");
20615 if (SrcSz == 32 && Subtarget->hasFP16())
20620 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20621 "Unexpected type for custom-lowering FP_ROUND");
20625 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20637 if (v == 0xffffffff)
20649 bool ForCodeSize)
const {
20650 if (!Subtarget->hasVFP3Base())
20652 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20654 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20657 if (VT == MVT::f32)
20659 if (VT == MVT::f64 && Subtarget->hasFP64())
20672 case Intrinsic::arm_neon_vld1:
20673 case Intrinsic::arm_neon_vld2:
20674 case Intrinsic::arm_neon_vld3:
20675 case Intrinsic::arm_neon_vld4:
20676 case Intrinsic::arm_neon_vld2lane:
20677 case Intrinsic::arm_neon_vld3lane:
20678 case Intrinsic::arm_neon_vld4lane:
20679 case Intrinsic::arm_neon_vld2dup:
20680 case Intrinsic::arm_neon_vld3dup:
20681 case Intrinsic::arm_neon_vld4dup: {
20684 auto &
DL =
I.getDataLayout();
20685 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20687 Info.ptrVal =
I.getArgOperand(0);
20689 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20695 case Intrinsic::arm_neon_vld1x2:
20696 case Intrinsic::arm_neon_vld1x3:
20697 case Intrinsic::arm_neon_vld1x4: {
20700 auto &
DL =
I.getDataLayout();
20701 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20703 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20705 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20710 case Intrinsic::arm_neon_vst1:
20711 case Intrinsic::arm_neon_vst2:
20712 case Intrinsic::arm_neon_vst3:
20713 case Intrinsic::arm_neon_vst4:
20714 case Intrinsic::arm_neon_vst2lane:
20715 case Intrinsic::arm_neon_vst3lane:
20716 case Intrinsic::arm_neon_vst4lane: {
20719 auto &
DL =
I.getDataLayout();
20720 unsigned NumElts = 0;
20721 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20722 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20725 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20728 Info.ptrVal =
I.getArgOperand(0);
20730 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20736 case Intrinsic::arm_neon_vst1x2:
20737 case Intrinsic::arm_neon_vst1x3:
20738 case Intrinsic::arm_neon_vst1x4: {
20741 auto &
DL =
I.getDataLayout();
20742 unsigned NumElts = 0;
20743 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20744 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20747 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20750 Info.ptrVal =
I.getArgOperand(0);
20752 Info.align =
I.getParamAlign(0).valueOrOne();
20757 case Intrinsic::arm_mve_vld2q:
20758 case Intrinsic::arm_mve_vld4q: {
20762 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
20764 Info.ptrVal =
I.getArgOperand(0);
20771 case Intrinsic::arm_mve_vst2q:
20772 case Intrinsic::arm_mve_vst4q: {
20775 Type *VecTy =
I.getArgOperand(1)->getType();
20776 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
20778 Info.ptrVal =
I.getArgOperand(0);
20785 case Intrinsic::arm_mve_vldr_gather_base:
20786 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
20788 Info.ptrVal =
nullptr;
20790 Info.align =
Align(1);
20794 case Intrinsic::arm_mve_vldr_gather_base_wb:
20795 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
20797 Info.ptrVal =
nullptr;
20798 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
20799 Info.align =
Align(1);
20803 case Intrinsic::arm_mve_vldr_gather_offset:
20804 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
20806 Info.ptrVal =
nullptr;
20811 Info.align =
Align(1);
20815 case Intrinsic::arm_mve_vstr_scatter_base:
20816 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
20818 Info.ptrVal =
nullptr;
20819 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
20820 Info.align =
Align(1);
20824 case Intrinsic::arm_mve_vstr_scatter_base_wb:
20825 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
20827 Info.ptrVal =
nullptr;
20828 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
20829 Info.align =
Align(1);
20833 case Intrinsic::arm_mve_vstr_scatter_offset:
20834 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
20836 Info.ptrVal =
nullptr;
20841 Info.align =
Align(1);
20845 case Intrinsic::arm_ldaex:
20846 case Intrinsic::arm_ldrex: {
20847 auto &
DL =
I.getDataLayout();
20848 Type *ValTy =
I.getParamElementType(0);
20851 Info.ptrVal =
I.getArgOperand(0);
20853 Info.align =
DL.getABITypeAlign(ValTy);
20857 case Intrinsic::arm_stlex:
20858 case Intrinsic::arm_strex: {
20859 auto &
DL =
I.getDataLayout();
20860 Type *ValTy =
I.getParamElementType(1);
20863 Info.ptrVal =
I.getArgOperand(1);
20865 Info.align =
DL.getABITypeAlign(ValTy);
20869 case Intrinsic::arm_stlexd:
20870 case Intrinsic::arm_strexd:
20872 Info.memVT = MVT::i64;
20873 Info.ptrVal =
I.getArgOperand(2);
20875 Info.align =
Align(8);
20879 case Intrinsic::arm_ldaexd:
20880 case Intrinsic::arm_ldrexd:
20882 Info.memVT = MVT::i64;
20883 Info.ptrVal =
I.getArgOperand(0);
20885 Info.align =
Align(8);
20900 assert(Ty->isIntegerTy());
20902 unsigned Bits = Ty->getPrimitiveSizeInBits();
20903 if (Bits == 0 || Bits > 32)
20909 unsigned Index)
const {
20919 if (!Subtarget->hasDataBarrier()) {
20923 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
20924 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
20925 Builder.getInt32(0), Builder.getInt32(7),
20926 Builder.getInt32(10), Builder.getInt32(5)};
20927 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
20937 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
20958 if (Subtarget->preferISHSTBarriers())
20991 bool has64BitAtomicStore;
20992 if (Subtarget->isMClass())
20993 has64BitAtomicStore =
false;
20994 else if (Subtarget->isThumb())
20995 has64BitAtomicStore = Subtarget->hasV7Ops();
20997 has64BitAtomicStore = Subtarget->hasV6Ops();
20999 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21013 bool has64BitAtomicLoad;
21014 if (Subtarget->isMClass())
21015 has64BitAtomicLoad =
false;
21016 else if (Subtarget->isThumb())
21017 has64BitAtomicLoad = Subtarget->hasV7Ops();
21019 has64BitAtomicLoad = Subtarget->hasV6Ops();
21035 if (Subtarget->isMClass())
21036 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21037 else if (Subtarget->isThumb())
21038 hasAtomicRMW = Subtarget->hasV7Ops();
21040 hasAtomicRMW = Subtarget->hasV6Ops();
21041 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21064 bool HasAtomicCmpXchg;
21065 if (Subtarget->isMClass())
21066 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21067 else if (Subtarget->isThumb())
21068 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21070 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21072 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21079 return InsertFencesForAtomic;
21084 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21089 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21092 RTLIB::LibcallImpl SecurityCookieVar =
21094 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21095 SecurityCookieVar != RTLIB::Unsupported) {
21106 F->addParamAttr(0, Attribute::AttrKind::InReg);
21113 unsigned &
Cost)
const {
21115 if (!Subtarget->hasNEON())
21144 unsigned Opcode =
Op.getOpcode();
21146 case ARMISD::VORRIMM:
21147 case ARMISD::VBICIMM:
21155 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21159 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21164 if (!Subtarget->hasV7Ops())
21170 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21172 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21180 if (Subtarget->hasMinSize() && !Subtarget->isTargetWindows())
21189 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21195 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21197 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21200 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21202 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21203 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21204 if (!Subtarget->isLittle())
21206 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21207 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21208 return Builder.CreateOr(
21209 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21213 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21214 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21217 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21218 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21223 if (!Subtarget->hasV7Ops())
21225 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21231 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21239 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21243 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21244 if (!Subtarget->isLittle())
21246 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21249 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21253 CallInst *CI = Builder.CreateCall(
21254 Strex, {Builder.CreateZExtOrBitCast(
21264 return Subtarget->isMClass();
21272 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21279 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21282 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21290 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21298 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21301 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21306 if (Subtarget->hasNEON() && VecSize == 64)
21308 return VecSize % 128 == 0;
21312 if (Subtarget->hasNEON())
21314 if (Subtarget->hasMVEIntegerOps())
21334 "Invalid interleave factor");
21335 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21337 "Unmatched number of shufflevectors and indices");
21342 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21345 Type *EltTy = VecTy->getElementType();
21348 Align Alignment = LI->getAlign();
21366 Value *BaseAddr = LI->getPointerOperand();
21368 if (NumLoads > 1) {
21372 VecTy->getNumElements() / NumLoads);
21378 if (Subtarget->hasNEON()) {
21379 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21380 Type *Tys[] = {VecTy, PtrTy};
21381 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21382 Intrinsic::arm_neon_vld3,
21383 Intrinsic::arm_neon_vld4};
21386 Ops.push_back(BaseAddr);
21387 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21389 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21392 assert((Factor == 2 || Factor == 4) &&
21393 "expected interleave factor of 2 or 4 for MVE");
21395 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21396 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21397 Type *Tys[] = {VecTy, PtrTy};
21400 Ops.push_back(BaseAddr);
21401 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21411 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21415 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21416 VecTy->getNumElements() * Factor);
21422 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21424 unsigned Index = Indices[i];
21426 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21430 SubVec = Builder.CreateIntToPtr(
21434 SubVecs[SV].push_back(SubVec);
21443 auto &SubVec = SubVecs[SVI];
21446 SVI->replaceAllUsesWith(WideVec);
21482 const APInt &GapMask)
const {
21484 "Invalid interleave factor");
21489 "Unexpected mask on store");
21492 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21494 unsigned LaneLen = VecTy->getNumElements() / Factor;
21495 Type *EltTy = VecTy->getElementType();
21499 Align Alignment =
SI->getAlign();
21516 Type *IntTy =
DL.getIntPtrType(EltTy);
21521 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21522 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21528 Value *BaseAddr =
SI->getPointerOperand();
21530 if (NumStores > 1) {
21533 LaneLen /= NumStores;
21543 if (Subtarget->hasNEON()) {
21544 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21545 Intrinsic::arm_neon_vst3,
21546 Intrinsic::arm_neon_vst4};
21547 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21548 Type *Tys[] = {PtrTy, SubVecTy};
21551 Ops.push_back(BaseAddr);
21553 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21554 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21556 assert((Factor == 2 || Factor == 4) &&
21557 "expected interleave factor of 2 or 4 for MVE");
21559 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21560 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21561 Type *Tys[] = {PtrTy, SubVecTy};
21564 Ops.push_back(BaseAddr);
21566 for (
unsigned F = 0;
F < Factor;
F++) {
21567 Ops.push_back(Builder.getInt32(
F));
21568 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21574 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21577 if (StoreCount > 0)
21578 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21579 BaseAddr, LaneLen * Factor);
21584 for (
unsigned i = 0; i < Factor; i++) {
21585 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21586 if (Mask[IdxI] >= 0) {
21587 Shuffles.
push_back(Builder.CreateShuffleVector(
21590 unsigned StartMask = 0;
21591 for (
unsigned j = 1; j < LaneLen; j++) {
21592 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21593 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21594 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21604 Shuffles.
push_back(Builder.CreateShuffleVector(
21625 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21629 Members += SubMembers;
21635 Members += SubMembers * AT->getNumElements();
21636 }
else if (Ty->isFloatTy()) {
21641 }
else if (Ty->isDoubleTy()) {
21653 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21655 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21657 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21670 return (Members > 0 && Members <= 4);
21676 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21678 return ABITypeAlign;
21683 assert(StackAlign &&
"data layout string is missing stack alignment");
21684 return std::min(ABITypeAlign, *StackAlign);
21693 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21702 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
21703 return IsHA || IsIntArray;
21707 const Constant *PersonalityFn)
const {
21715 const Constant *PersonalityFn)
const {
21728void ARMTargetLowering::insertCopiesSplitCSR(
21732 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21742 RC = &ARM::GPRRegClass;
21743 else if (ARM::DPRRegClass.
contains(*
I))
21744 RC = &ARM::DPRRegClass;
21754 assert(Entry->getParent()->getFunction().hasFnAttribute(
21755 Attribute::NoUnwind) &&
21756 "Function should be nounwind in insertCopiesSplitCSR!");
21757 Entry->addLiveIn(*
I);
21762 for (
auto *Exit : Exits)
21764 TII->get(TargetOpcode::COPY), *
I)
21775 return Subtarget->hasMVEIntegerOps();
21785 unsigned NumElements = VTy->getNumElements();
21792 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
21793 return Subtarget->hasMVEFloatOps();
21798 return Subtarget->hasMVEIntegerOps() &&
21799 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
21800 ScalarTy->isIntegerTy(32));
21804 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
21815 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
21817 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
21819 if (TyWidth > 128) {
21820 int Stride = Ty->getNumElements() / 2;
21824 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
21826 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
21827 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
21828 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
21829 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
21830 Value *LowerSplitAcc =
nullptr;
21831 Value *UpperSplitAcc =
nullptr;
21834 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
21835 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
21839 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
21841 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
21843 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
21844 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
21851 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
21854 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
21856 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
21857 {ConstRotation, InputB, InputA});
21862 auto *ConstHalving = ConstantInt::get(IntTy, 1);
21865 ConstRotation = ConstantInt::get(IntTy, 0);
21867 ConstRotation = ConstantInt::get(IntTy, 1);
21869 if (!ConstRotation)
21872 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
21873 {ConstHalving, ConstRotation, InputA, InputB});
unsigned const MachineRegisterInfo * MRI
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 bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool isNegatedInteger(SDValue Op)
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 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 LowerUADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG)
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 ConvertBooleanCarryToCarryFlag(SDValue BoolCarry, SelectionDAG &DAG)
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 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 SDValue ConvertCarryFlagToBooleanCarry(SDValue Flags, EVT VT, SelectionDAG &DAG)
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 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 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 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 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 LowerSTORE(SDValue Op, 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 PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, Value *Offset, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, Value *Offset, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned int Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
const ARMBaseRegisterInfo & getRegisterInfo() const
const uint32_t * getSjLjDispatchPreservedMask(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const uint32_t * getTLSCallPreservedMask(const MachineFunction &MF) const
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
int getVarArgsFrameIndex() const
int getPromotedConstpoolIncrease() const
SmallPtrSet< const GlobalVariable *, 2 > & getGlobalsPromotedToConstantPool()
void setArgumentStackToRestore(unsigned v)
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
void setPromotedConstpoolIncrease(int Sz)
bool isThumb1OnlyFunction() const
void setArgRegsSaveSize(unsigned s)
bool isCmseNSEntryFunction() const
void setReturnRegsCount(unsigned s)
void setVarArgsFrameIndex(int Index)
unsigned getArgRegsSaveSize() const
void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV)
Indicate to the backend that GV has had its storage changed to inside a constant pool.
void setIsSplitCSR(bool s)
void setArgumentStackSize(unsigned size)
unsigned getArgumentStackSize() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
bool isTargetWindows() const
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
Align getDualLoadStoreAlignment() const
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool isReadOnly(const GlobalValue *GV) const
unsigned getMaxSupportedInterleaveFactor() const override
Get the maximum supported factor for interleaved memory accesses.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
unsigned getNumInterleavedAccesses(VectorType *VecTy, const DataLayout &DL) const
Returns the number of interleaved accesses that will be generated when lowering accesses of the given...
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Align getABIAlignmentForCallingConv(Type *ArgTy, const DataLayout &DL) const override
Return the correct alignment for the current calling convention.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
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 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.
void insertSSPDeclarations(Module &M) const override
Inserts necessary declarations for SSP (stack protection) purpose.
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.
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
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
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for this result type with this index.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
isShuffleMaskLegal - Targets can use this to indicate that they only support some VECTOR_SHUFFLE oper...
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.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
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
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
bool supportKCFIBundles() const override
Return true if the target supports kcfi operand bundles.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
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.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
bool isFloatingPointOperation() const
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
The address of a basic block.
static BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
LLVM_ABI int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, uint32_t BitWidth) const
If this is a constant FP splat and the splatted constant FP is an exact power or 2,...
CCState - This class holds information needed while lowering arguments and return values.
void getInRegsParamInfo(unsigned InRegsParamRecordIndex, unsigned &BeginReg, unsigned &EndReg) const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
void rewindByValRegsInfo()
unsigned getInRegsParamsProcessed() const
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd)
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
unsigned getInRegsParamsCount() const
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
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...
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...
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
StringRef getPrivateGlobalPrefix() const
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.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
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)
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...
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & 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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
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.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI unsigned createJumpTableIndex(const std::vector< MachineBasicBlock * > &DestBBs)
createJumpTableIndex - Create a new jump table.
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
This class is used to represent an MLOAD node.
This class is used to represent an MSTORE node.
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
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.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
This instruction constructs a fixed permutation of two input vectors.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
StringRef - Represent a constant reference to a string, i.e.
const unsigned char * bytes_end() const
constexpr size_t size() const
size - Get the string size.
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.
CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const
Get the CallingConv that should be used for the specified libcall.
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
void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked load does or does not work with the specified type and ind...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked store does or does not work with the specified type and in...
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
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 ...
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
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.
virtual void insertSSPDeclarations(Module &M) const
Inserts necessary declarations for SSP (stack protection) purpose.
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.
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...
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 a n/2-bit urem by constant and other arit...
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 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).
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
ExceptionHandling getExceptionModel() const
Return the ExceptionHandling to use, considering TargetOptions and the Triple's default.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
unsigned EmitCallGraphSection
Emit section containing call graph metadata.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
Base class of all SIMD vector types.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static CondCodes getOppositeCondition(CondCodes CC)
@ SECREL
Thread Pointer Offset.
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
TOF
Target Operand Flag enum.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2Offset(unsigned AM2Opc)
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
AddrOpc getAM2Op(unsigned AM2Opc)
bool isBitFieldInvertedMask(unsigned v)
const unsigned FPStatusBits
const unsigned FPReservedBits
const unsigned RoundingBitsPos
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
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...
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ 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.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ 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 ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ 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.
@ 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...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ SSUBO
Same for subtraction.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ 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.
@ 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...
@ 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.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ SMULO
Same for multiplication.
@ 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.
@ 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.
@ 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.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ 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.
@ 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.
@ 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.
@ 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...
@ 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 * > Tys={})
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.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
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.
FunctionAddr VTableAddr Value
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.
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ SjLj
setjmp/longjmp based exceptions
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
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)
FunctionAddr VTableAddr Count
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.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
FunctionAddr VTableAddr uintptr_t uintptr_t Data
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...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
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.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
bool isUnknown() const
Returns true if we don't know any bits.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)