84#include "llvm/IR/IntrinsicsARM.h"
119#define DEBUG_TYPE "arm-isel"
122STATISTIC(NumOptimizedImms,
"Number of times immediates were optimized");
123STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
124STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
126 "Number of constants with their storage promoted into constant pools");
130 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
135 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
140 cl::desc(
"Maximum size of constant to promote into a constant pool"),
144 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
149 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
154 cl::desc(
"Maximum number of base-updates to check generating postindex."),
162 ARM::R0, ARM::R1, ARM::R2, ARM::R3
176void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
177 if (VT != PromotedLdStVT) {
186 if (ElemTy != MVT::f64)
190 if (ElemTy == MVT::i32) {
234void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
236 addTypeForNEON(VT, MVT::f64);
239void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
241 addTypeForNEON(VT, MVT::v2f64);
244void ARMTargetLowering::setAllExpand(
MVT VT) {
257void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
264void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
265 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
267 for (
auto VT : IntTypes) {
342 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
343 for (
auto VT : FloatTypes) {
417 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
418 for (
auto VT : LongTypes) {
435 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
436 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
437 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
454 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
463 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
464 for (
auto VT : pTypes) {
515 RegInfo(Subtarget->getRegisterInfo()),
516 Itins(Subtarget->getInstrItineraryData()) {
522 const Triple &TT = TM.getTargetTriple();
524 if (Subtarget->isThumb1Only())
529 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
530 Subtarget->hasFPRegs()) {
534 if (!Subtarget->hasVFP2Base()) {
535 setAllExpand(MVT::f32);
544 if (!Subtarget->hasFP64()) {
545 setAllExpand(MVT::f64);
555 if (Subtarget->hasFullFP16()) {
570 if (Subtarget->hasBF16()) {
572 setAllExpand(MVT::bf16);
573 if (!Subtarget->hasFullFP16())
587 addAllExtLoads(VT, InnerVT,
Expand);
596 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
599 if (!Subtarget->hasV8_1MMainlineOps())
602 if (!Subtarget->isThumb1Only())
611 if (Subtarget->hasMVEIntegerOps())
612 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
615 if (Subtarget->hasLOB()) {
619 if (Subtarget->hasNEON()) {
620 addDRTypeForNEON(MVT::v2f32);
621 addDRTypeForNEON(MVT::v8i8);
622 addDRTypeForNEON(MVT::v4i16);
623 addDRTypeForNEON(MVT::v2i32);
624 addDRTypeForNEON(MVT::v1i64);
626 addQRTypeForNEON(MVT::v4f32);
627 addQRTypeForNEON(MVT::v2f64);
628 addQRTypeForNEON(MVT::v16i8);
629 addQRTypeForNEON(MVT::v8i16);
630 addQRTypeForNEON(MVT::v4i32);
631 addQRTypeForNEON(MVT::v2i64);
633 if (Subtarget->hasFullFP16()) {
634 addQRTypeForNEON(MVT::v8f16);
635 addDRTypeForNEON(MVT::v4f16);
638 if (Subtarget->hasBF16()) {
639 addQRTypeForNEON(MVT::v8bf16);
640 addDRTypeForNEON(MVT::v4bf16);
644 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
684 if (Subtarget->hasNEON()) {
797 if (!Subtarget->hasVFP4Base()) {
806 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
815 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
824 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
832 if (Subtarget->hasMVEIntegerOps()) {
837 if (Subtarget->hasMVEFloatOps()) {
841 if (!Subtarget->hasFP64()) {
893 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
896 if (Subtarget->hasFullFP16()) {
904 if (!Subtarget->hasFP16()) {
933 if (!Subtarget->isThumb1Only()) {
952 if (TT.isTargetAEABI() && !Subtarget->allowsUnalignedMem()) {
964 if (!Subtarget->isThumb1Only()) {
973 if (Subtarget->hasDSP()) {
983 if (Subtarget->hasBaseDSP()) {
991 if (Subtarget->isThumb1Only()) {
995 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
996 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1011 if (Subtarget->hasMVEIntegerOps())
1015 if (Subtarget->isThumb1Only()) {
1021 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1035 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1044 if (Subtarget->hasPerfMon())
1048 if (!Subtarget->hasV6Ops())
1051 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1052 : Subtarget->hasDivideInARMMode();
1059 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1071 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1072 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1075 HasStandaloneRem =
false;
1102 if (TT.isOSWindows())
1109 InsertFencesForAtomic =
false;
1110 if (Subtarget->hasAnyDataBarrier() &&
1111 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1115 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1120 if (!Subtarget->hasAcquireRelease() ||
1123 InsertFencesForAtomic =
true;
1129 if (Subtarget->hasDataBarrier())
1130 InsertFencesForAtomic =
true;
1150 if (!InsertFencesForAtomic) {
1157 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1169 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1170 Subtarget->hasForced32BitAtomics()) {
1184 if (!Subtarget->hasV6Ops()) {
1190 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1191 !Subtarget->isThumb1Only()) {
1220 if (Subtarget->hasFullFP16()) {
1230 if (Subtarget->hasFullFP16())
1245 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1246 !Subtarget->isThumb1Only()) {
1253 if (!Subtarget->hasVFP4Base()) {
1259 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1261 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1269 if (!Subtarget->hasFP16()) {
1286 if (Subtarget->hasFPARMv8Base()) {
1296 if (Subtarget->hasFP64())
1300 if (Subtarget->hasNEON()) {
1310 if (Subtarget->hasFullFP16()) {
1347 if (Subtarget->hasNEON()) {
1359 if (Subtarget->hasV8Ops()) {
1369 if (Subtarget->hasFullFP16()) {
1392 if (TT.isOSWindows()) {
1409 if (Subtarget->hasMVEIntegerOps())
1412 if (Subtarget->hasV6Ops())
1414 if (Subtarget->isThumb1Only())
1417 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1418 Subtarget->isThumb2()) {
1424 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1425 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1456 return Subtarget->useSoftFloat();
1460 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1473std::pair<const TargetRegisterClass *, uint8_t>
1484 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1485 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1486 RRC = &ARM::DPRRegClass;
1491 if (Subtarget->useNEONForSinglePrecisionFP())
1494 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1495 case MVT::v4f32:
case MVT::v2f64:
1496 RRC = &ARM::DPRRegClass;
1500 RRC = &ARM::DPRRegClass;
1504 RRC = &ARM::DPRRegClass;
1508 return std::make_pair(RRC,
Cost);
1517 if (Subtarget->hasMVEIntegerOps())
1532 if (Subtarget->hasNEON()) {
1533 if (VT == MVT::v4i64)
1534 return &ARM::QQPRRegClass;
1535 if (VT == MVT::v8i64)
1536 return &ARM::QQQQPRRegClass;
1538 if (Subtarget->hasMVEIntegerOps()) {
1539 if (VT == MVT::v4i64)
1540 return &ARM::MQQPRRegClass;
1541 if (VT == MVT::v8i64)
1542 return &ARM::MQQQQPRRegClass;
1551 Align &PrefAlign)
const {
1558 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1570 unsigned NumVals =
N->getNumValues();
1574 for (
unsigned i = 0; i != NumVals; ++i) {
1575 EVT VT =
N->getValueType(i);
1576 if (VT == MVT::Glue || VT == MVT::Other)
1582 if (!
N->isMachineOpcode())
1590 if (
MCID.getNumDefs() == 0)
1592 if (!Itins->isEmpty() &&
1593 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1607 return Const->getZExtValue() == 16;
1615 return Const->getZExtValue() == 16;
1623 return Const->getZExtValue() == 16;
1692 bool isVarArg)
const {
1711 if (!Subtarget->isAAPCS_ABI())
1713 else if (Subtarget->isTargetHardFloat() && !isVarArg)
1719 if (!Subtarget->isAAPCS_ABI()) {
1720 if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() && !isVarArg)
1723 }
else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1724 !Subtarget->useSoftFloat() && !isVarArg)
1732 bool isVarArg)
const {
1733 return CCAssignFnForNode(
CC,
false, isVarArg);
1737 bool isVarArg)
const {
1738 return CCAssignFnForNode(
CC,
true, isVarArg);
1745 bool isVarArg)
const {
1772 if (Subtarget->hasFullFP16()) {
1773 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1785 if (Subtarget->hasFullFP16()) {
1786 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1799SDValue ARMTargetLowering::LowerCallResult(
1803 SDValue ThisVal,
bool isCmseNSCall)
const {
1811 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1812 CCValAssign VA = RVLocs[i];
1816 if (i == 0 && isThisReturn) {
1818 "unexpected return calling convention register assignment");
1836 if (!Subtarget->isLittle())
1838 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1853 if (!Subtarget->isLittle())
1855 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1885 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1896std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1898 bool IsTailCall,
int SPDiff)
const {
1900 MachinePointerInfo DstInfo;
1920 return std::make_pair(DstAddr, DstInfo);
1929ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1942 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1945 int SrcFI = SrcFrameIdxNode->getIndex();
1946 int DstFI = DstFrameIdxNode->getIndex();
1948 "byval passed in non-fixed stack slot");
1970 if (SrcOffset == DstOffset)
1978 RegsToPassVector &RegsToPass,
1984 SDValue fmrrd = DAG.
getNode(ARMISD::VMOVRRD, dl,
1985 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1986 unsigned id = Subtarget->isLittle() ? 0 : 1;
1998 MachinePointerInfo DstInfo;
1999 std::tie(DstAddr, DstInfo) =
2000 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2017 SelectionDAG &DAG = CLI.
DAG;
2019 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2020 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2021 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2022 SDValue Chain = CLI.
Chain;
2028 const CallBase *CB = CLI.
CB;
2031 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2033 MachineFunction::CallSiteInfo CSInfo;
2034 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2035 bool isThisReturn =
false;
2036 bool isCmseNSCall =
false;
2037 bool isSibCall =
false;
2038 bool PreferIndirect =
false;
2039 bool GuardWithBTI =
false;
2049 !Subtarget->noBTIAtReturnTwice())
2057 isCmseNSCall =
true;
2060 if (!Subtarget->supportsTailCall())
2076 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2077 count_if(GV->users(), [&BB](
const User *U) {
2078 return isa<Instruction>(U) &&
2079 cast<Instruction>(U)->getParent() == BB;
2086 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2100 "site marked musttail");
2103 unsigned NumBytes = CCInfo.getStackSize();
2112 if (isTailCall && !isSibCall) {
2113 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2114 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2119 assert(StackAlign &&
"data layout string is missing stack alignment");
2120 NumBytes =
alignTo(NumBytes, *StackAlign);
2125 SPDiff = NumReusableBytes - NumBytes;
2129 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2145 RegsToPassVector RegsToPass;
2153 for (
const ForwardedRegister &
F : Forwards) {
2155 RegsToPass.push_back(std::make_pair(
F.PReg, Val));
2165 DenseMap<unsigned, SDValue> ByValTemporaries;
2166 SDValue ByValTempChain;
2169 for (
const CCValAssign &VA : ArgLocs) {
2171 SDValue Src = OutVals[ArgIdx];
2172 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2174 if (!
Flags.isByVal())
2178 MachinePointerInfo DstInfo;
2179 std::tie(Dst, DstInfo) =
2180 computeAddrForCallArg(dl, DAG, VA, SDValue(),
true, SPDiff);
2181 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2183 if (Copy == NoCopy) {
2188 }
else if (Copy == CopyOnce) {
2192 ByValTemporaries[ArgIdx] = Src;
2194 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2198 int TempFrameIdx = MFI.CreateStackObject(
2199 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2207 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2208 SDValue
Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2210 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2211 ByValTemporaries[ArgIdx] = Temp;
2214 if (!ByValCopyChains.
empty())
2224 bool AfterFormalArgLoads =
false;
2228 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2230 ++i, ++realArgIdx) {
2231 CCValAssign &VA = ArgLocs[i];
2232 SDValue Arg = OutVals[realArgIdx];
2233 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2234 bool isByVal =
Flags.isByVal();
2254 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2256 if (ByValTempChain) {
2261 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2262 if (Outs[
I].
Flags.isByVal())
2265 SDValue OutVal = OutVals[
I];
2270 FrameIndexSDNode *FIN =
2275 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2278 for (
const CCValAssign &VA : ArgLocs) {
2286 if (!IncomingLoad.
empty()) {
2294 AfterFormalArgLoads =
true;
2306 auto ArgVT = Outs[realArgIdx].ArgVT;
2307 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2325 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2326 StackPtr, MemOpChains, isTailCall, SPDiff);
2330 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2331 StackPtr, MemOpChains, isTailCall, SPDiff);
2335 MachinePointerInfo DstInfo;
2336 std::tie(DstAddr, DstInfo) =
2337 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2341 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2342 StackPtr, MemOpChains, isTailCall, SPDiff);
2344 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2345 Outs[0].VT == MVT::i32) {
2347 "unexpected calling convention register assignment");
2349 "unexpected use of 'returned'");
2350 isThisReturn =
true;
2355 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2356 }
else if (isByVal) {
2358 unsigned offset = 0;
2362 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2363 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2366 bool NeedsStackCopy;
2367 if (
auto It = ByValTemporaries.
find(realArgIdx);
2368 It != ByValTemporaries.
end()) {
2369 ByValSrc = It->second;
2370 NeedsStackCopy =
true;
2373 NeedsStackCopy = !isTailCall;
2377 if (CurByValIdx < ByValArgsCount) {
2378 unsigned RegBegin, RegEnd;
2379 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2383 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2387 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2390 RegsToPass.push_back(std::make_pair(j,
Load));
2395 offset = RegEnd - RegBegin;
2397 CCInfo.nextInRegsParam();
2402 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2405 MachinePointerInfo DstInfo;
2406 std::tie(Dst, DstInfo) =
2407 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2415 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2416 SDValue
Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2423 MachinePointerInfo DstInfo;
2424 std::tie(DstAddr, DstInfo) =
2425 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2427 SDValue
Store = DAG.
getStore(Chain, dl, Arg, DstAddr, DstInfo);
2432 if (!MemOpChains.
empty())
2438 for (
const auto &[
Reg,
N] : RegsToPass) {
2446 bool isDirect =
false;
2449 const Triple &
TT = TM.getTargetTriple();
2450 const GlobalValue *GVal =
nullptr;
2452 GVal =
G->getGlobal();
2453 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2455 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2456 bool isLocalARMFunc =
false;
2459 if (Subtarget->genLongCalls()) {
2461 if (isPIC && Subtarget->genExecuteOnly())
2463 "position-independent code is not supported");
2464 if (Subtarget->isROPI())
2471 if (Subtarget->genExecuteOnly()) {
2474 if (Subtarget->useMovt())
2497 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2503 const char *Sym = S->getSymbol();
2505 if (Subtarget->genExecuteOnly()) {
2508 if (Subtarget->useMovt())
2515 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
2521 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2522 SDValue GOTOffset = DAG.
getLoad(
2525 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
2526 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, GOTOffset, PICLabel);
2538 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2545 if (!PreferIndirect) {
2550 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2552 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2553 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2555 ARMISD::WrapperPIC, dl, PtrVt,
2562 }
else if (Subtarget->isTargetCOFF()) {
2563 assert(Subtarget->isTargetWindows() &&
2564 "Windows is the only supported COFF target");
2568 else if (!TM.shouldAssumeDSOLocal(GVal))
2575 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2584 const char *Sym = S->getSymbol();
2585 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2587 ARMConstantPoolValue *CPV =
2589 ARMPCLabelIndex, 4);
2591 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2595 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
2596 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2603 assert(!isARMFunc && !isDirect &&
2604 "Cannot handle call to ARM function or direct call");
2608 "call to non-secure function would require "
2609 "passing arguments on stack",
2615 "call to non-secure function would return value through pointer",
2622 if (Subtarget->isThumb()) {
2624 CallOpc = ARMISD::t2CALL_BTI;
2625 else if (isCmseNSCall)
2626 CallOpc = ARMISD::tSECALL;
2627 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2628 CallOpc = ARMISD::CALL_NOLINK;
2630 CallOpc = ARMISD::CALL;
2632 if (!isDirect && !Subtarget->hasV5TOps())
2633 CallOpc = ARMISD::CALL_NOLINK;
2634 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2636 !Subtarget->hasMinSize())
2638 CallOpc = ARMISD::CALL_NOLINK;
2640 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2647 if (isTailCall && !isSibCall) {
2652 std::vector<SDValue>
Ops;
2653 Ops.push_back(Chain);
2654 Ops.push_back(Callee);
2662 for (
const auto &[
Reg,
N] : RegsToPass)
2666 const uint32_t *
Mask;
2667 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2675 isThisReturn =
false;
2681 assert(Mask &&
"Missing call preserved mask for calling convention");
2685 Ops.push_back(InGlue);
2689 SDValue Ret = DAG.
getNode(ARMISD::TC_RETURN, dl, MVT::Other,
Ops);
2698 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2712 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2718 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2719 InVals, isThisReturn,
2720 isThisReturn ? OutVals[0] : SDValue(), isCmseNSCall);
2727void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2728 Align Alignment)
const {
2736 unsigned AlignInRegs =
Alignment.value() / 4;
2737 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2738 for (
unsigned i = 0; i < Waste; ++i)
2744 unsigned Excess = 4 * (ARM::R4 -
Reg);
2751 if (NSAAOffset != 0 &&
Size > Excess) {
2763 unsigned ByValRegBegin =
Reg;
2764 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2768 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2774 Size = std::max<int>(
Size - Excess, 0);
2782bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2788 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2789 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2790 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2791 const SelectionDAG &DAG = CLI.
DAG;
2796 assert(Subtarget->supportsTailCall());
2809 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2811 if (!(Subtarget->isThumb1Only() ||
2812 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2813 AddressRegisters.
insert(ARM::R12);
2814 for (
const CCValAssign &AL : ArgLocs)
2816 AddressRegisters.
erase(
AL.getLocReg());
2817 if (AddressRegisters.
empty()) {
2818 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2837 <<
" (guaranteed tail-call CC)\n");
2838 return CalleeCC == CallerCC;
2843 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2845 if (isCalleeStructRet != isCallerStructRet) {
2858 const GlobalValue *GV =
G->getGlobal();
2861 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2862 TT.isOSBinFormatMachO())) {
2879 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2880 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2881 if (CalleeCC != CallerCC) {
2882 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2883 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2892 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2902 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2921 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2930 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2943 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2946 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2950 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2955 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2977 bool isLittleEndian = Subtarget->isLittle();
2980 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2989 "secure entry function would return value through pointer",
2994 for (
unsigned i = 0, realRVLocIdx = 0;
2996 ++i, ++realRVLocIdx) {
2997 CCValAssign &VA = RVLocs[i];
3000 SDValue Arg = OutVals[realRVLocIdx];
3001 bool ReturnF16 =
false;
3003 if (Subtarget->hasFullFP16() && Subtarget->isTargetHardFloat()) {
3036 auto RetVT = Outs[realRVLocIdx].ArgVT;
3057 SDValue HalfGPRs = DAG.
getNode(ARMISD::VMOVRRD, dl,
3058 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3062 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3068 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3079 SDValue fmrrd = DAG.
getNode(ARMISD::VMOVRRD, dl,
3080 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3082 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3087 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3097 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3123 !Subtarget->isMClass()) {
3124 if (Subtarget->isThumb1Only())
3131 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3134bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3135 if (
N->getNumValues() != 1)
3137 if (!
N->hasNUsesOfValue(1, 0))
3140 SDValue TCChain = Chain;
3141 SDNode *
Copy = *
N->user_begin();
3145 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3147 TCChain =
Copy->getOperand(0);
3148 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3149 SDNode *VMov =
Copy;
3151 SmallPtrSet<SDNode*, 2>
Copies;
3152 for (SDNode *U : VMov->
users()) {
3160 for (SDNode *U : VMov->
users()) {
3161 SDValue UseChain =
U->getOperand(0);
3169 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3177 if (!
Copy->hasOneUse())
3184 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3186 TCChain =
Copy->getOperand(0);
3191 bool HasRet =
false;
3192 for (
const SDNode *U :
Copy->users()) {
3193 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3194 U->getOpcode() != ARMISD::INTRET_GLUE)
3206bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3207 if (!Subtarget->supportsTailCall())
3224 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3240 EVT PtrVT =
Op.getValueType();
3250 if (Subtarget->genExecuteOnly()) {
3255 auto GV =
new GlobalVariable(
3261 return LowerGlobalAddress(GA, DAG);
3267 if (Subtarget->isThumb1Only())
3268 CPAlign = std::max(CPAlign,
Align(4));
3274 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3281 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3290 unsigned ARMPCLabelIndex = 0;
3296 if (!IsPositionIndependent) {
3299 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3306 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3310 if (!IsPositionIndependent)
3312 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex,
DL, MVT::i32);
3313 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3341ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3344 "This function expects a Darwin target");
3349 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3354 SDValue FuncTLVGet = DAG.
getLoad(
3355 MVT::i32,
DL, Chain, DescAddr,
3370 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3376 Chain = DAG.
getCopyToReg(Chain,
DL, ARM::R0, DescAddr, SDValue());
3379 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3385ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3388 "Windows specific TLS lowering");
3395 SDValue
Ops[] = {Chain,
3405 SDValue TEB = CurrentTEB.
getValue(0);
3412 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3420 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3421 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3427 MachinePointerInfo());
3434 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3447 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3449 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3451 ARMConstantPoolValue *CPV =
3459 SDValue Chain =
Argument.getValue(1);
3461 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
3462 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3469 TargetLowering::CallLoweringInfo CLI(DAG);
3474 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3475 return CallResult.first;
3484 const GlobalValue *GV = GA->
getGlobal();
3490 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3494 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3497 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3498 ARMConstantPoolValue *CPV =
3505 PtrVT, dl, Chain,
Offset,
3509 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
3513 PtrVT, dl, Chain,
Offset,
3518 ARMConstantPoolValue *CPV =
3523 PtrVT, dl, Chain,
Offset,
3539 if (
TT.isOSDarwin())
3540 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3542 if (
TT.isOSWindows())
3543 return LowerGlobalTLSAddressWindows(
Op, DAG);
3546 assert(
TT.isOSBinFormatELF() &&
"Only ELF implemented here");
3552 return LowerToTLSGeneralDynamicModel(GA, DAG);
3555 return LowerToTLSExecModels(GA, DAG, model);
3564 while (!Worklist.
empty()) {
3572 if (!
I ||
I->getParent()->getParent() !=
F)
3601 if (!GVar || !GVar->hasInitializer() ||
3602 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3603 !GVar->hasLocalLinkage())
3608 auto *
Init = GVar->getInitializer();
3610 Init->needsDynamicRelocation())
3622 unsigned RequiredPadding = 4 - (
Size % 4);
3623 bool PaddingPossible =
3624 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3629 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3653 if (RequiredPadding != 4) {
3658 while (RequiredPadding--)
3670 ++NumConstpoolPromoted;
3671 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3676 if (!(GV = GA->getAliaseeObject()))
3679 return V->isConstant();
3688 return LowerGlobalAddressWindows(
Op, DAG);
3690 return LowerGlobalAddressELF(
Op, DAG);
3692 return LowerGlobalAddressDarwin(
Op, DAG);
3704 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3717 }
else if (Subtarget->isROPI() && IsRO) {
3722 }
else if (Subtarget->isRWPI() && !IsRO) {
3725 if (Subtarget->useMovt()) {
3728 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3730 ARMConstantPoolValue *CPV =
3733 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3747 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3748 if (Subtarget->useMovt())
3752 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3756 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3765 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3766 "ROPI/RWPI not currently supported for Darwin");
3771 if (Subtarget->useMovt())
3782 if (Subtarget->isGVIndirectSymbol(GV))
3791 "non-Windows COFF is not supported");
3792 assert(Subtarget->useMovt() &&
3793 "Windows on ARM expects to use movw/movt");
3794 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3795 "ROPI/RWPI not currently supported for Windows");
3802 else if (!TM.shouldAssumeDSOLocal(GV))
3825 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3826 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3827 Op.getOperand(1), Val);
3833 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3840 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3844SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3847 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3851 case Intrinsic::arm_gnu_eabi_mcount: {
3855 SDValue Chain =
Op.getOperand(0);
3857 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3858 const uint32_t *
Mask =
3860 assert(Mask &&
"Missing call preserved mask for calling convention");
3863 SDValue ReturnAddress =
3865 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3869 if (Subtarget->isThumb())
3872 ARM::tBL_PUSHLR, dl, ResultTys,
3873 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3874 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3878 {ReturnAddress, Callee, RegisterMask, Chain}),
3887 unsigned IntNo =
Op.getConstantOperandVal(0);
3890 default:
return SDValue();
3891 case Intrinsic::localaddress: {
3893 const auto *RegInfo = Subtarget->getRegisterInfo();
3894 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
3896 Op.getSimpleValueType());
3898 case Intrinsic::eh_recoverfp: {
3899 SDValue FnOp =
Op.getOperand(1);
3904 "llvm.eh.recoverfp must take a function as the first argument");
3905 const auto *RegInfo = Subtarget->getRegisterInfo();
3908 MachineBasicBlock &
MBB = *MF.
begin();
3914 case Intrinsic::thread_pointer: {
3916 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3918 case Intrinsic::arm_cls: {
3922 const SDValue &Operand =
Op.getOperand(1);
3923 const EVT VTy =
Op.getValueType();
3926 case Intrinsic::arm_cls64: {
3932 case Intrinsic::arm_neon_vcls:
3933 case Intrinsic::arm_mve_vcls: {
3936 const EVT VTy =
Op.getValueType();
3939 case Intrinsic::eh_sjlj_lsda: {
3941 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3946 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3947 ARMConstantPoolValue *CPV =
3951 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3956 if (IsPositionIndependent) {
3957 SDValue PICLabel = DAG.
getConstant(ARMPCLabelIndex, dl, MVT::i32);
3958 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3962 case Intrinsic::arm_neon_vabs:
3965 case Intrinsic::arm_neon_vabds:
3966 if (
Op.getValueType().isInteger())
3968 Op.getOperand(1),
Op.getOperand(2));
3970 case Intrinsic::arm_neon_vabdu:
3972 Op.getOperand(1),
Op.getOperand(2));
3973 case Intrinsic::arm_neon_vmulls:
3974 case Intrinsic::arm_neon_vmullu: {
3975 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3976 ? ARMISD::VMULLs : ARMISD::VMULLu;
3977 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3978 Op.getOperand(1),
Op.getOperand(2));
3980 case Intrinsic::arm_neon_vminnm:
3981 case Intrinsic::arm_neon_vmaxnm: {
3982 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3984 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3985 Op.getOperand(1),
Op.getOperand(2));
3987 case Intrinsic::arm_neon_vminu:
3988 case Intrinsic::arm_neon_vmaxu: {
3989 if (
Op.getValueType().isFloatingPoint())
3991 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3993 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3994 Op.getOperand(1),
Op.getOperand(2));
3996 case Intrinsic::arm_neon_vmins:
3997 case Intrinsic::arm_neon_vmaxs: {
3999 if (!
Op.getValueType().isFloatingPoint()) {
4000 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4002 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4003 Op.getOperand(1),
Op.getOperand(2));
4005 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4007 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
4008 Op.getOperand(1),
Op.getOperand(2));
4010 case Intrinsic::arm_neon_vtbl1:
4011 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
4012 Op.getOperand(1),
Op.getOperand(2));
4013 case Intrinsic::arm_neon_vtbl2:
4014 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
4015 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4016 case Intrinsic::arm_mve_pred_i2v:
4017 case Intrinsic::arm_mve_pred_v2i:
4018 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
4020 case Intrinsic::arm_mve_vreinterpretq:
4021 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
4023 case Intrinsic::arm_mve_lsll:
4024 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
4025 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4026 case Intrinsic::arm_mve_asrl:
4027 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
4028 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4029 case Intrinsic::arm_mve_vsli:
4030 return DAG.
getNode(ARMISD::VSLIIMM, SDLoc(
Op),
Op->getVTList(),
4031 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4032 case Intrinsic::arm_mve_vsri:
4033 return DAG.
getNode(ARMISD::VSRIIMM, SDLoc(
Op),
Op->getVTList(),
4034 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4045 if (!Subtarget->hasDataBarrier()) {
4049 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4050 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4051 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
4061 }
else if (Subtarget->preferISHSTBarriers() &&
4070 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4078 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4080 return Op.getOperand(0);
4083 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4085 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4087 return Op.getOperand(0);
4089 unsigned isData =
Op.getConstantOperandVal(4);
4090 if (Subtarget->isThumb()) {
4092 isRead = ~isRead & 1;
4093 isData = ~isData & 1;
4096 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4111 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4119 const SDLoc &dl)
const {
4121 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4125 RC = &ARM::tGPRRegClass;
4127 RC = &ARM::GPRRegClass;
4141 MVT::i32, dl, Root, FIN,
4147 if (!Subtarget->isLittle())
4149 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4162 const Value *OrigArg,
4163 unsigned InRegsParamRecordIdx,
4164 int ArgOffset,
unsigned ArgSize)
const {
4178 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4179 unsigned RBegin, REnd;
4184 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4189 ArgOffset = -4 * (ARM::R4 - RBegin);
4199 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4203 MachinePointerInfo(OrigArg, 4 * i));
4208 if (!MemOps.
empty())
4217 unsigned TotalArgRegsSaveSize,
4218 bool ForceMutable)
const {
4220 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4229 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4233bool ARMTargetLowering::splitValueIntoRegisterParts(
4235 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
4237 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4249SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4251 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
4252 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4255 SDValue Val = Parts[0];
4265SDValue ARMTargetLowering::LowerFormalArguments(
4272 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4281 unsigned CurArgIdx = 0;
4293 unsigned ArgRegBegin = ARM::R4;
4294 for (
const CCValAssign &VA : ArgLocs) {
4300 if (!
Flags.isByVal())
4304 unsigned RBegin, REnd;
4306 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4312 int lastInsIndex = -1;
4316 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4319 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4323 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4324 CCValAssign &VA = ArgLocs[i];
4325 if (Ins[VA.
getValNo()].isOrigArg()) {
4326 std::advance(CurOrigArg,
4327 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4328 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4339 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4346 MVT::f64, dl, Chain, FIN,
4349 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4357 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4361 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4362 RC = &ARM::HPRRegClass;
4363 else if (RegVT == MVT::f32)
4364 RC = &ARM::SPRRegClass;
4365 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4366 RegVT == MVT::v4bf16)
4367 RC = &ARM::DPRRegClass;
4368 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4369 RegVT == MVT::v8bf16)
4370 RC = &ARM::QPRRegClass;
4371 else if (RegVT == MVT::i32)
4373 : &ARM::GPRRegClass;
4410 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4419 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4425 if (index != lastInsIndex)
4427 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4433 if (
Flags.isByVal()) {
4434 assert(Ins[index].isOrigArg() &&
4435 "Byval arguments cannot be implicit");
4439 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4473 lastInsIndex = index;
4480 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4481 TotalArgRegsSaveSize);
4485 "secure entry function must not be variadic", dl.
getDebugLoc()));
4506 SmallVectorImpl<ForwardedRegister> &Forwards =
4519 assert(StackAlign &&
"data layout string is missing stack alignment");
4520 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4529 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4538 return CFP->getValueAPF().isPosZero();
4541 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4542 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4545 return CFP->getValueAPF().isPosZero();
4548 Op->getValueType(0) == MVT::f64) {
4552 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4561 if (
Op->getFlags().hasNoSignedWrap())
4577 (isIntEqualitySetCC(
CC) ||
4587 if (ST.isThumb1Only() || !
Op.hasOneUse())
4590 unsigned Opc =
Op.getOpcode();
4593 return ShiftAmt->getZExtValue() <= 31 ? 1 : 0;
4596 return ST.isThumb() ? 0 : 1;
4604 return ST.isThumb() ? 0 : 1;
4620 uint32_t MaskValue = Mask->getZExtValue();
4623 if (!
isMask_32(MaskValue) || MaskValue == 1 || MaskValue == 0xff ||
4624 MaskValue == 0xffff || MaskValue == ~0U)
4636 const SDLoc &dl)
const {
4643 for (
unsigned I = 0;
I != 2; ++
I) {
4653 unsigned C = RHSC->getZExtValue();
4711 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4715 unsigned Mask =
LHS.getConstantOperandVal(1);
4717 uint64_t RHSV = RHSC->getZExtValue();
4718 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4720 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4721 SDValue ShiftAmt = DAG.
getConstant(ShiftBits, dl, MVT::i32);
4734 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4737 LHS.getConstantOperandVal(1) < 31) {
4738 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4748 unsigned CompareType;
4751 CompareType = ARMISD::CMP;
4756 CompareType = ARMISD::CMPZ;
4765 if (CompareType != ARMISD::CMPZ &&
isCMN(
RHS,
CC, DAG)) {
4766 CompareType = ARMISD::CMN;
4768 }
else if (CompareType != ARMISD::CMPZ &&
isCMN(
LHS,
CC, DAG)) {
4769 CompareType = ARMISD::CMN;
4783 if (CompareType == ARMISD::CMP)
4811 bool Signaling)
const {
4812 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4818 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4827std::pair<SDValue, SDValue>
4830 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4832 SDValue
Value, OverflowCmp;
4833 SDValue
LHS =
Op.getOperand(0);
4834 SDValue
RHS =
Op.getOperand(1);
4842 switch (
Op.getOpcode()) {
4894 return std::make_pair(
Value, OverflowCmp);
4907 return Cmp.getValue(1);
4935 return DAG.
getNode(ARMISD::CMOV,
DL, VT, Zero, One, ARMcc, Flags);
4943 SDValue
LHS =
Op.getOperand(0);
4944 SDValue
RHS =
Op.getOperand(1);
4947 EVT VT =
Op.getValueType();
4948 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4951 switch (
Op.getOpcode()) {
4964 SDValue OverflowCmp, ARMcc;
4965 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4971 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4974 ARMcc, OverflowCmp);
4984 EVT VT =
Op.getValueType();
4985 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4995 switch (
Op->getOpcode()) {
4997 NewOpcode = ARMISD::UQADD8b;
5000 NewOpcode = ARMISD::QADD8b;
5003 NewOpcode = ARMISD::UQSUB8b;
5006 NewOpcode = ARMISD::QSUB8b;
5011 switch (
Op->getOpcode()) {
5013 NewOpcode = ARMISD::UQADD16b;
5016 NewOpcode = ARMISD::QADD16b;
5019 NewOpcode = ARMISD::UQSUB16b;
5022 NewOpcode = ARMISD::QSUB16b;
5030 DAG.
getNode(NewOpcode, dl, MVT::i32,
5037 SDValue
Cond =
Op.getOperand(0);
5038 SDValue SelectTrue =
Op.getOperand(1);
5039 SDValue SelectFalse =
Op.getOperand(2);
5041 unsigned Opc =
Cond.getOpcode();
5043 if (
Cond.getResNo() == 1 &&
5049 SDValue
Value, OverflowCmp;
5051 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5052 EVT VT =
Op.getValueType();
5054 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
5062 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
5063 const ConstantSDNode *CMOVTrue =
5065 const ConstantSDNode *CMOVFalse =
5068 if (CMOVTrue && CMOVFalse) {
5074 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5076 False = SelectFalse;
5077 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5083 return getCMOV(dl,
Op.getValueType(),
True,
False,
Cond.getOperand(2),
5084 Cond.getOperand(3), DAG);
5094 bool &swpCmpOps,
bool &swpVselOps) {
5122 swpCmpOps = !swpCmpOps;
5123 swpVselOps = !swpVselOps;
5146 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5148 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5150 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5152 SDValue TrueLow =
TrueVal.getValue(0);
5153 SDValue TrueHigh =
TrueVal.getValue(1);
5154 SDValue FalseLow =
FalseVal.getValue(0);
5155 SDValue FalseHigh =
FalseVal.getValue(1);
5157 SDValue
Low = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, FalseLow, TrueLow,
5159 SDValue
High = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, FalseHigh, TrueHigh,
5164 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5185 ((
K ==
LHS &&
K == TrueVal) || (
K ==
RHS &&
K == FalseVal))) ||
5187 ((
K ==
RHS &&
K == TrueVal) || (
K ==
LHS &&
K == FalseVal)));
5208 EVT VT =
Op.getValueType();
5230 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5243 int64_t PosVal = std::max(Val1, Val2);
5244 int64_t NegVal = std::min(Val1, Val2);
5256 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5259 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5291 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5296 if (*
K != KTmp || V != VTmp)
5307bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5309 return !Subtarget->hasVFP2Base();
5311 return !Subtarget->hasFP64();
5313 return !Subtarget->hasFullFP16();
5321 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5329 if (TVal == ~FVal) {
5330 Opcode = ARMISD::CSINV;
5331 }
else if (TVal == ~FVal + 1) {
5332 Opcode = ARMISD::CSNEG;
5333 }
else if (TVal + 1 == FVal) {
5334 Opcode = ARMISD::CSINC;
5335 }
else if (TVal == FVal + 1) {
5336 Opcode = ARMISD::CSINC;
5339 InvertCond = !InvertCond;
5346 if (Opcode != ARMISD::CSINC &&
5350 InvertCond = !InvertCond;
5356 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5359 InvertCond = !InvertCond;
5366 EVT VT =
Op.getValueType();
5370 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5380 SDValue LowerSatConstant;
5382 if (VT == MVT::i32 &&
5394 SDValue
LHS =
Op.getOperand(0);
5395 SDValue
RHS =
Op.getOperand(1);
5401 if (
Op.getValueType().isInteger()) {
5409 LHS.getValueType() ==
RHS.getValueType()) {
5410 EVT VT =
LHS.getValueType();
5416 Shift = DAG.
getNOT(dl, Shift, VT);
5428 if (
LHS.getValueType() == MVT::i32) {
5432 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5437 SDValue
Cmp = getARMCmp(
LHS,
RHS,
CC, ARMcc, DAG, dl);
5438 EVT VT =
Op.getValueType();
5439 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5443 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5448 if (!
RHS.getNode()) {
5454 if (
LHS.getValueType() == MVT::i32) {
5465 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5466 TrueVal.getValueType() == MVT::f32 ||
5467 TrueVal.getValueType() == MVT::f64)) {
5477 SDValue
Cmp = getARMCmp(
LHS,
RHS,
CC, ARMcc, DAG, dl);
5481 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5491 if (Subtarget->hasFPARMv8Base() &&
5493 (
TrueVal.getValueType() == MVT::f16 ||
5494 TrueVal.getValueType() == MVT::f32 ||
5495 TrueVal.getValueType() == MVT::f64)) {
5496 bool swpCmpOps =
false;
5497 bool swpVselOps =
false;
5509 SDValue ARMcc = DAG.
getConstant(CondCode, dl, MVT::i32);
5510 SDValue
Cmp = getVFPCmp(
LHS,
RHS, DAG, dl);
5511 SDValue
Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5513 SDValue ARMcc2 = DAG.
getConstant(CondCode2, dl, MVT::i32);
5514 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5524 if (!
N->hasOneUse())
5527 if (!
N->getNumValues())
5529 EVT VT =
Op.getValueType();
5530 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5547 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5548 Ld->getPointerInfo(), Ld->getAlign(),
5549 Ld->getMemOperand()->getFlags());
5565 SDValue Ptr = Ld->getBasePtr();
5567 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5568 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5573 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5574 Ld->getPointerInfo().getWithOffset(4),
5576 Ld->getMemOperand()->getFlags());
5587 SDValue Chain =
Op.getOperand(0);
5589 SDValue
LHS =
Op.getOperand(2);
5590 SDValue
RHS =
Op.getOperand(3);
5591 SDValue Dest =
Op.getOperand(4);
5594 bool LHSSeenZero =
false;
5596 bool RHSSeenZero =
false;
5598 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5609 if (
LHS.getValueType() == MVT::f32) {
5614 SDValue
Cmp = getARMCmp(
LHS,
RHS,
CC, ARMcc, DAG, dl);
5615 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5627 SDValue
Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5628 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5643 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5655 SDValue Chain =
Op.getOperand(0);
5656 SDValue
Cond =
Op.getOperand(1);
5657 SDValue Dest =
Op.getOperand(2);
5662 unsigned Opc =
Cond.getOpcode();
5664 !Subtarget->isThumb1Only();
5665 if (
Cond.getResNo() == 1 &&
5673 SDValue
Value, OverflowCmp;
5675 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5680 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5688 SDValue Chain =
Op.getOperand(0);
5690 SDValue
LHS =
Op.getOperand(2);
5691 SDValue
RHS =
Op.getOperand(3);
5692 SDValue Dest =
Op.getOperand(4);
5695 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5700 if (!
RHS.getNode()) {
5708 unsigned Opc =
LHS.getOpcode();
5710 !Subtarget->isThumb1Only();
5720 SDValue
Value, OverflowCmp;
5722 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5729 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5733 if (
LHS.getValueType() == MVT::i32) {
5735 SDValue
Cmp = getARMCmp(
LHS,
RHS,
CC, ARMcc, DAG, dl);
5736 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5739 SDNodeFlags
Flags =
Op->getFlags();
5740 if (
Flags.hasNoNaNs() &&
5745 if (SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5752 SDValue ARMcc = DAG.
getConstant(CondCode, dl, MVT::i32);
5753 SDValue
Cmp = getVFPCmp(
LHS,
RHS, DAG, dl);
5754 SDValue
Ops[] = {Chain, Dest, ARMcc,
Cmp};
5755 SDValue Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5758 SDValue
Ops[] = {Res, Dest, ARMcc,
Cmp};
5759 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5765 SDValue Chain =
Op.getOperand(0);
5766 SDValue
Table =
Op.getOperand(1);
5767 SDValue
Index =
Op.getOperand(2);
5773 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5776 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5781 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5782 Addr,
Op.getOperand(2), JTI);
5786 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5790 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5793 DAG.
getLoad(PTy, dl, Chain, Addr,
5796 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5801 EVT VT =
Op.getValueType();
5804 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5805 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5813 const EVT OpTy =
Op.getOperand(0).getValueType();
5814 if (
OpTy == MVT::v4f32)
5816 else if (
OpTy == MVT::v4f16 && HasFullFP16)
5818 else if (
OpTy == MVT::v8f16 && HasFullFP16)
5823 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5826 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5831 EVT VT =
Op.getValueType();
5835 bool IsStrict =
Op->isStrictFPOpcode();
5836 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5838 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5849 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
5851 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5852 CallOptions, Loc, Chain);
5861 EVT VT =
Op.getValueType();
5863 EVT FromVT =
Op.getOperand(0).getValueType();
5865 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5867 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5868 Subtarget->hasFP64())
5870 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5871 Subtarget->hasFullFP16())
5873 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5874 Subtarget->hasMVEFloatOps())
5876 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5877 Subtarget->hasMVEFloatOps())
5880 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5897 EVT VT =
Op.getValueType();
5900 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5906 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5907 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5908 "Invalid type for custom lowering!");
5913 if (VT == MVT::v4f32)
5914 DestVecType = MVT::v4i32;
5915 else if (VT == MVT::v4f16 && HasFullFP16)
5916 DestVecType = MVT::v4i16;
5917 else if (VT == MVT::v8f16 && HasFullFP16)
5918 DestVecType = MVT::v8i16;
5924 switch (
Op.getOpcode()) {
5936 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5941 EVT VT =
Op.getValueType();
5945 bool IsStrict =
Op->isStrictFPOpcode();
5946 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5948 if (isUnsupportedFloatingType(VT)) {
5957 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
5959 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5960 CallOptions, Loc, Chain);
5969 SDValue Tmp0 =
Op.getOperand(0);
5970 SDValue Tmp1 =
Op.getOperand(1);
5972 EVT VT =
Op.getValueType();
5976 bool UseNEON = !InGPR && Subtarget->hasNEON();
5981 SDValue
Mask = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v2i32,
5983 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5990 if (SrcVT == MVT::f32) {
5993 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5996 }
else if (VT == MVT::f32)
5997 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
6012 if (VT == MVT::f32) {
6024 if (SrcVT == MVT::f64)
6030 SDValue Mask1 = DAG.
getConstant(0x80000000, dl, MVT::i32);
6031 SDValue Mask2 = DAG.
getConstant(0x7fffffff, dl, MVT::i32);
6033 if (VT == MVT::f32) {
6046 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
6054 EVT VT =
Op.getValueType();
6056 unsigned Depth =
Op.getConstantOperandVal(0);
6058 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
6062 MachinePointerInfo());
6071 const ARMBaseRegisterInfo &ARI =
6072 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
6077 EVT VT =
Op.getValueType();
6079 unsigned Depth =
Op.getConstantOperandVal(0);
6084 MachinePointerInfo());
6092 return StringSwitch<Register>(
RegName)
6093 .Case(
"sp", ARM::SP)
6104 assert(
N->getValueType(0) == MVT::i64
6105 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6108 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6148 const APInt &APIntIndex = Index->getAPIntValue();
6150 NewIndex *= APIntIndex;
6175 SDValue
Op =
N->getOperand(0);
6179 EVT SrcVT =
Op.getValueType();
6180 EVT DstVT =
N->getValueType(0);
6182 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6183 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6184 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6187 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6188 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6189 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6196 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6208 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6216 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6218 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6220 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6240 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6249 EVT VT =
Op.getValueType();
6252 SDValue ShOpLo =
Op.getOperand(0);
6253 SDValue ShOpHi =
Op.getOperand(1);
6254 SDValue ShAmt =
Op.getOperand(2);
6267 SDValue LoBigShift = DAG.
getNode(
Opc, dl, VT, ShOpHi, ExtraShAmt);
6268 SDValue CmpLo = getARMCmp(ExtraShAmt, DAG.
getConstant(0, dl, MVT::i32),
6271 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6273 SDValue HiSmallShift = DAG.
getNode(
Opc, dl, VT, ShOpHi, ShAmt);
6278 SDValue CmpHi = getARMCmp(ExtraShAmt, DAG.
getConstant(0, dl, MVT::i32),
6281 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6292 EVT VT =
Op.getValueType();
6295 SDValue ShOpLo =
Op.getOperand(0);
6296 SDValue ShOpHi =
Op.getOperand(1);
6297 SDValue ShAmt =
Op.getOperand(2);
6309 SDValue HiBigShift = DAG.
getNode(
ISD::SHL, dl, VT, ShOpLo, ExtraShAmt);
6310 SDValue CmpHi = getARMCmp(ExtraShAmt, DAG.
getConstant(0, dl, MVT::i32),
6313 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6315 SDValue CmpLo = getARMCmp(ExtraShAmt, DAG.
getConstant(0, dl, MVT::i32),
6318 SDValue
Lo = DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift,
6332 SDValue Chain =
Op.getOperand(0);
6333 SDValue
Ops[] = {Chain,
6334 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6351 SDValue Chain =
Op->getOperand(0);
6352 SDValue RMValue =
Op->getOperand(1);
6373 SDValue
Ops[] = {Chain,
6386 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6393 SDValue Chain =
Op->getOperand(0);
6394 SDValue
Mode =
Op->getOperand(1);
6398 SDValue
Ops[] = {Chain,
6405 SDValue FPSCRMasked =
6408 SDValue InputMasked =
6414 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6421 SDValue Chain =
Op->getOperand(0);
6425 SDValue
Ops[] = {Chain,
6432 SDValue FPSCRMasked = DAG.
getNode(
6435 SDValue Ops2[] = {Chain,
6444 EVT VT =
N->getValueType(0);
6445 if (VT.
isVector() && ST->hasNEON()) {
6465 unsigned NumBits =
ElemTy.getSizeInBits();
6467 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6477 if (
ElemTy == MVT::i64) {
6490 if (!ST->hasV6T2Ops())
6499 EVT VT =
N->getValueType(0);
6502 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6503 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6504 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6505 "Unexpected type for custom ctpop lowering");
6513 unsigned EltSize = 8;
6536 Op =
Op.getOperand(0);
6538 APInt SplatBits, SplatUndef;
6539 unsigned SplatBitSize;
6542 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6544 SplatBitSize > ElementBits)
6555 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6559 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6570 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6575 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6576 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6585 EVT VT =
N->getValueType(0);
6600 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6602 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6607 "unexpected vector shift opcode");
6609 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6610 unsigned VShiftOpc =
6611 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6612 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6618 EVT ShiftVT =
N->getOperand(1).getValueType();
6621 unsigned VShiftOpc =
6622 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6623 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6628 EVT VT =
N->getValueType(0);
6637 "Unknown shift to lower!");
6639 unsigned ShOpc =
N->getOpcode();
6640 if (ST->hasMVEIntegerOps()) {
6642 unsigned ShPartsOpc = ARMISD::LSLL;
6663 ShPartsOpc = ARMISD::LSRL;
6665 ShPartsOpc = ARMISD::ASRL;
6670 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6684 if (ST->isThumb1Only())
6689 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6693 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6697 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6705 bool Invert =
false;
6712 EVT VT =
Op.getValueType();
6720 assert(ST->hasMVEIntegerOps() &&
6721 "No hardware support for integer vector comparison!");
6723 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6744 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6748 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6758 switch (SetCCOpcode) {
6762 if (ST->hasMVEFloatOps()) {
6765 Invert =
true; [[fallthrough]];
6790 Result = DAG.
getNOT(dl, Result, VT);
6793 case ISD::SETUO: Invert =
true; [[fallthrough]];
6802 Result = DAG.
getNOT(dl, Result, VT);
6808 switch (SetCCOpcode) {
6811 if (ST->hasMVEIntegerOps()) {
6814 Invert =
true; [[fallthrough]];
6836 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6839 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6844 Result = DAG.
getNOT(dl, Result, VT);
6869 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6872 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6878 Result = DAG.
getNOT(dl, Result, VT);
6887 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6904 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6915 unsigned OpCmode,
Imm;
6926 switch (SplatBitSize) {
6931 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6934 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6939 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6940 if ((SplatBits & ~0xff) == 0) {
6946 if ((SplatBits & ~0xff00) == 0) {
6949 Imm = SplatBits >> 8;
6959 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6960 if ((SplatBits & ~0xff) == 0) {
6966 if ((SplatBits & ~0xff00) == 0) {
6969 Imm = SplatBits >> 8;
6972 if ((SplatBits & ~0xff0000) == 0) {
6975 Imm = SplatBits >> 16;
6978 if ((SplatBits & ~0xff000000) == 0) {
6981 Imm = SplatBits >> 24;
6988 if ((SplatBits & ~0xffff) == 0 &&
6989 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6992 Imm = SplatBits >> 8;
7000 if ((SplatBits & ~0xffffff) == 0 &&
7001 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
7004 Imm = SplatBits >> 16;
7020 unsigned ImmMask = 1;
7022 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
7023 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
7025 }
else if ((SplatBits & BitMask) != 0) {
7034 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
7048 EVT VT =
Op.getValueType();
7049 bool IsDouble = (VT == MVT::f64);
7055 if (
ST->genExecuteOnly()) {
7057 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
7058 "Unexpected architecture");
7076 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
7081 if (!
ST->hasVFP3Base())
7086 if (IsDouble && !Subtarget->hasFP64())
7093 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7103 SDValue VecConstant = DAG.
getNode(ARMISD::VMOVFPIMM,
DL, MVT::v2f32,
7111 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7120 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7126 if (NewVal != SDValue()) {
7128 SDValue VecConstant = DAG.
getNode(ARMISD::VMOVIMM,
DL, VMovVT,
7143 if (NewVal != SDValue()) {
7145 SDValue VecConstant = DAG.
getNode(ARMISD::VMVNIMM,
DL, VMovVT, NewVal);
7174 unsigned ExpectedElt =
Imm;
7175 for (
unsigned i = 1; i < NumElts; ++i) {
7179 if (ExpectedElt == NumElts)
7182 if (M[i] < 0)
continue;
7183 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7191 bool &ReverseVEXT,
unsigned &
Imm) {
7193 ReverseVEXT =
false;
7204 unsigned ExpectedElt =
Imm;
7205 for (
unsigned i = 1; i < NumElts; ++i) {
7209 if (ExpectedElt == NumElts * 2) {
7214 if (M[i] < 0)
continue;
7215 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7230 return VT == MVT::v8i8 && M.size() == 8;
7236 unsigned &WhichResult,
7239 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7240 return ARMISD::VTRN;
7241 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7242 return ARMISD::VUZP;
7243 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7244 return ARMISD::VZIP;
7248 return ARMISD::VTRN;
7250 return ARMISD::VUZP;
7252 return ARMISD::VZIP;
7261 if (NumElts != M.size())
7265 for (
unsigned i = 0; i != NumElts; ++i)
7266 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7275 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7283 int Ofs = Top ? 1 : 0;
7284 int Upper = SingleSource ? 0 : NumElts;
7285 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7286 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7288 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7297 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7306 unsigned Offset = Top ? 0 : 1;
7307 unsigned N = SingleSource ? 0 : NumElts;
7308 for (
unsigned i = 0; i < NumElts; i += 2) {
7309 if (M[i] >= 0 && M[i] != (
int)i)
7311 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7320 if (NumElts != M.size())
7328 unsigned Off0 = rev ? NumElts / 2 : 0;
7329 unsigned Off1 = rev ? 0 : NumElts / 2;
7330 for (
unsigned i = 0; i < NumElts; i += 2) {
7331 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7333 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7349 if (!ST->hasMVEFloatOps())
7354 if (VT != MVT::v8f16)
7375 for (
unsigned i = 1; i < 4; i++) {
7390 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7402 if (!ST->hasMVEFloatOps())
7407 if (VT != MVT::v4f32)
7423 for (
unsigned i = 1; i < 4; i++) {
7434 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7446 Val =
N->getAsZExtVal();
7448 if (ST->isThumb1Only()) {
7449 if (Val <= 255 || ~Val <= 255)
7461 EVT VT =
Op.getValueType();
7463 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7467 unsigned BitsPerBool;
7471 }
else if (NumElts == 4) {
7474 }
else if (NumElts == 8) {
7477 }
else if (NumElts == 16) {
7488 return U.get().isUndef() || U.get() == FirstOp;
7492 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7496 unsigned Bits32 = 0;
7497 for (
unsigned i = 0; i < NumElts; ++i) {
7501 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7503 Bits32 |= BoolMask << (i * BitsPerBool);
7509 for (
unsigned i = 0; i < NumElts; ++i) {
7522 if (!ST->hasMVEIntegerOps())
7526 EVT VT =
Op.getValueType();
7536 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7540 for (
unsigned I = 2;
I < NumElts;
I++) {
7556 switch (
N->getOpcode()) {
7567 return N->getOperand(1).getNode() ==
Op;
7569 switch (
N->getConstantOperandVal(0)) {
7570 case Intrinsic::arm_mve_add_predicated:
7571 case Intrinsic::arm_mve_mul_predicated:
7572 case Intrinsic::arm_mve_qadd_predicated:
7573 case Intrinsic::arm_mve_vhadd:
7574 case Intrinsic::arm_mve_hadd_predicated:
7575 case Intrinsic::arm_mve_vqdmulh:
7576 case Intrinsic::arm_mve_qdmulh_predicated:
7577 case Intrinsic::arm_mve_vqrdmulh:
7578 case Intrinsic::arm_mve_qrdmulh_predicated:
7579 case Intrinsic::arm_mve_vqdmull:
7580 case Intrinsic::arm_mve_vqdmull_predicated:
7582 case Intrinsic::arm_mve_sub_predicated:
7583 case Intrinsic::arm_mve_qsub_predicated:
7584 case Intrinsic::arm_mve_vhsub:
7585 case Intrinsic::arm_mve_hsub_predicated:
7586 return N->getOperand(2).getNode() ==
Op;
7601 EVT VT =
Op.getValueType();
7609 APInt SplatBits, SplatUndef;
7610 unsigned SplatBitSize;
7612 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7619 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7621 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7622 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7623 : SplatBitSize == 16 ? MVT::v8i16
7626 SDValue VDup = DAG.
getNode(ARMISD::VDUP, dl, DupVT, Const);
7627 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7630 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7631 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7636 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7639 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, Val);
7640 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7644 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7646 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7649 SDValue Vmov = DAG.
getNode(ARMISD::VMVNIMM, dl, VmovVT, Val);
7650 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7654 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7658 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7664 if (
ST->hasMVEIntegerOps() &&
7665 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7666 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7667 : SplatBitSize == 16 ? MVT::v8i16
7670 SDValue VDup = DAG.
getNode(ARMISD::VDUP, dl, DupVT, Const);
7671 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7684 bool isOnlyLowElement =
true;
7685 bool usesOnlyOneValue =
true;
7686 bool hasDominantValue =
false;
7691 DenseMap<SDValue, unsigned> ValueCounts;
7693 for (
unsigned i = 0; i < NumElts; ++i) {
7694 SDValue
V =
Op.getOperand(i);
7698 isOnlyLowElement =
false;
7702 unsigned &
Count = ValueCounts[
V];
7705 if (++
Count > (NumElts / 2)) {
7706 hasDominantValue =
true;
7710 if (ValueCounts.
size() != 1)
7711 usesOnlyOneValue =
false;
7712 if (!
Value.getNode() && !ValueCounts.
empty())
7715 if (ValueCounts.
empty())
7721 (VT != MVT::v8f16 ||
ST->hasFullFP16()))
7728 if (hasDominantValue && EltSize <= 32) {
7737 ConstantSDNode *constIndex;
7744 if (VT !=
Value->getOperand(0).getValueType()) {
7747 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7752 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7757 if (!usesOnlyOneValue) {
7760 for (
unsigned I = 0;
I < NumElts; ++
I) {
7765 Ops.push_back(
Op.getOperand(
I));
7775 assert(FVT == MVT::f32 || FVT == MVT::f16);
7776 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7777 for (
unsigned i = 0; i < NumElts; ++i)
7782 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7786 if (usesOnlyOneValue) {
7789 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7803 if (SDValue
shuffle = ReconstructShuffle(
Op, DAG))
7813 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7833 if (EltSize >= 32) {
7839 for (
unsigned i = 0; i < NumElts; ++i)
7852 (VT == MVT::v8f16 && !
ST->hasFullFP16())) {
7854 for (
unsigned i = 0 ; i < NumElts; ++i) {
7855 SDValue
V =
Op.getOperand(i);
7858 SDValue LaneIdx = DAG.
getConstant(i, dl, MVT::i32);
7873 EVT VT =
Op.getValueType();
7876 struct ShuffleSourceInfo {
7878 unsigned MinElt = std::numeric_limits<unsigned>::max();
7879 unsigned MaxElt = 0;
7889 int WindowScale = 1;
7891 ShuffleSourceInfo(SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7893 bool operator ==(SDValue OtherVec) {
return Vec == OtherVec; }
7899 for (
unsigned i = 0; i < NumElts; ++i) {
7900 SDValue
V =
Op.getOperand(i);
7914 SDValue SourceVec =
V.getOperand(0);
7916 if (Source == Sources.
end())
7920 unsigned EltNo =
V.getConstantOperandVal(1);
7927 if (Sources.
size() > 2)
7933 for (
auto &Source : Sources) {
7934 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
7935 if (SrcEltTy.
bitsLT(SmallestEltTy))
7936 SmallestEltTy = SrcEltTy;
7938 unsigned ResMultiplier =
7946 for (
auto &Src : Sources) {
7947 EVT SrcVT = Src.ShuffleVec.getValueType();
7951 if (SrcVTSize == VTSize)
7960 if (SrcVTSize < VTSize) {
7961 if (2 * SrcVTSize != VTSize)
7967 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
7971 if (SrcVTSize != 2 * VTSize)
7974 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
7979 if (Src.MinElt >= NumSrcElts) {
7984 Src.WindowBase = -NumSrcElts;
7985 }
else if (Src.MaxElt < NumSrcElts) {
7999 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8002 Src.WindowBase = -Src.MinElt;
8009 for (
auto &Src : Sources) {
8010 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8011 if (SrcEltTy == SmallestEltTy)
8014 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8016 Src.WindowBase *= Src.WindowScale;
8021 for (
auto Src : Sources)
8022 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8029 SDValue
Entry =
Op.getOperand(i);
8030 if (
Entry.isUndef())
8039 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8042 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8046 int *LaneMask = &
Mask[i * ResMultiplier];
8048 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8049 ExtractBase += NumElts * (Src - Sources.begin());
8050 for (
int j = 0;
j < LanesDefined; ++
j)
8051 LaneMask[j] = ExtractBase + j;
8057 assert(Sources.size() <= 2 &&
"Too many sources!");
8060 for (
unsigned i = 0; i < Sources.size(); ++i)
8067 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8089 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8109 unsigned PFIndexes[4];
8110 for (
unsigned i = 0; i != 4; ++i) {
8114 PFIndexes[i] = M[i];
8118 unsigned PFTableIndex =
8119 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8121 unsigned Cost = (PFEntry >> 30);
8127 bool ReverseVEXT, isV_UNDEF;
8128 unsigned Imm, WhichResult;
8131 if (EltSize >= 32 ||
8138 else if (Subtarget->hasNEON() &&
8143 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8146 else if (Subtarget->hasMVEIntegerOps() &&
8150 else if (Subtarget->hasMVEIntegerOps() &&
8164 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8165 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8166 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8169 if (LHSID == (1*9+2)*9+3)
return LHS;
8170 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8184 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8187 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8190 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8195 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8200 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8227 for (
int I : ShuffleMask)
8231 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8,
V1,
8234 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8,
V1, V2,
8240 EVT VT =
Op.getValueType();
8242 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8243 "Expect an v8i16/v16i8 type");
8249 std::vector<int> NewMask;
8253 NewMask.push_back(i);
8283 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8293 if (VT != MVT::v16i1)
8294 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8309 EVT VT =
Op.getValueType();
8313 assert(ST->hasMVEIntegerOps() &&
8314 "No support for vector shuffle of boolean predicates");
8324 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8340 "Expected identical vector type in expanded i1 shuffle!");
8344 PredAsVector2, ShuffleMask);
8349 if (VT == MVT::v2i1) {
8350 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8353 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8355 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8366 EVT VT =
Op.getValueType();
8370 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8371 "Unexpected vector type");
8373 int QuarterSize = NumElts / 4;
8382 for (
int i = 0; i <
Length; i++) {
8383 if (ShuffleMask[Start + i] >= 0) {
8384 if (ShuffleMask[Start + i] %
Length != i)
8386 MovIdx = ShuffleMask[Start + i] /
Length;
8394 for (
int i = 1; i <
Length; i++) {
8395 if (ShuffleMask[Start + i] >= 0 &&
8396 (ShuffleMask[Start + i] /
Length != MovIdx ||
8397 ShuffleMask[Start + i] %
Length != i))
8403 for (
int Part = 0; Part < 4; ++Part) {
8405 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8419 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8424 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8426 for (
int Part = 0; Part < 4; ++Part)
8427 for (
int i = 0; i < QuarterSize; i++)
8429 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8431 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8434 for (
int Part = 0; Part < 4; ++Part)
8450 EVT VT =
Op.getValueType();
8462 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8466 if (Mask[i] != i + BaseOffset) {
8467 if (OffElement == -1)
8473 return NonUndef > 2 && OffElement != -1;
8477 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8479 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8490 ShuffleMask[OffElement] < (
int)NumElts ?
V1 : V2,
8501 EVT VT =
Op.getValueType();
8505 if (ST->hasMVEIntegerOps() && EltSize == 1)
8516 if (EltSize <= 32) {
8520 if (Lane == -1) Lane = 0;
8524 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8531 bool IsScalarToVector =
true;
8532 for (
unsigned i = 1, e =
V1.getNumOperands(); i != e; ++i)
8533 if (!
V1.getOperand(i).isUndef()) {
8534 IsScalarToVector =
false;
8537 if (IsScalarToVector)
8538 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8540 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
V1,
8544 bool ReverseVEXT =
false;
8546 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT,
Imm)) {
8549 return DAG.
getNode(ARMISD::VEXT, dl, VT,
V1, V2,
8554 return DAG.
getNode(ARMISD::VREV64, dl, VT,
V1);
8556 return DAG.
getNode(ARMISD::VREV32, dl, VT,
V1);
8558 return DAG.
getNode(ARMISD::VREV16, dl, VT,
V1);
8570 unsigned WhichResult = 0;
8571 bool isV_UNDEF =
false;
8572 if (ST->hasNEON()) {
8574 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8581 if (ST->hasMVEIntegerOps()) {
8583 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2,
V1,
8586 return DAG.
getNode(ARMISD::VMOVN, dl, VT,
V1, V2,
8616 }) &&
"Unexpected shuffle index into UNDEF operand!");
8619 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8622 assert((WhichResult == 0) &&
8623 "In-place shuffle of concat can only have one result!");
8632 if (ST->hasMVEIntegerOps() && EltSize <= 32 &&
8633 (ST->hasFullFP16() || VT != MVT::v8f16)) {
8637 for (
bool Top : {
false,
true}) {
8638 for (
bool SingleSource : {
false,
true}) {
8639 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8644 SingleSource ?
V1 : V2);
8660 unsigned PFIndexes[4];
8661 for (
unsigned i = 0; i != 4; ++i) {
8662 if (ShuffleMask[i] < 0)
8665 PFIndexes[i] = ShuffleMask[i];
8669 unsigned PFTableIndex =
8670 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8672 unsigned Cost = (PFEntry >> 30);
8678 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8679 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8689 if (EltSize >= 32) {
8697 for (
unsigned i = 0; i < NumElts; ++i) {
8698 if (ShuffleMask[i] < 0)
8702 ShuffleMask[i] < (
int)NumElts ?
V1 : V2,
8710 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8714 if (ST->hasNEON() && VT == MVT::v8i8)
8718 if (ST->hasMVEIntegerOps())
8723 if (VT == MVT::v8f16 && !ST->hasFullFP16()) {
8725 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(0));
8727 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(1));
8729 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuf);
8737 EVT VecVT =
Op.getOperand(0).getValueType();
8740 assert(ST->hasMVEIntegerOps() &&
8741 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8744 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8745 unsigned Lane =
Op.getConstantOperandVal(2);
8746 unsigned LaneWidth =
8748 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8753 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8759 SDValue Lane =
Op.getOperand(2);
8763 SDValue Elt =
Op.getOperand(1);
8766 if (Subtarget->hasMVEIntegerOps() &&
8767 Op.getValueType().getScalarSizeInBits() == 1)
8783 SDValue VecIn =
Op.getOperand(0);
8791 IVecIn, IElt, Lane);
8800 EVT VecVT =
Op.getOperand(0).getValueType();
8803 assert(ST->hasMVEIntegerOps() &&
8804 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8807 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8808 unsigned Lane =
Op.getConstantOperandVal(1);
8809 unsigned LaneWidth =
8831 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8840 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8841 "Unexpected custom CONCAT_VECTORS lowering");
8843 "Unexpected custom CONCAT_VECTORS lowering");
8844 assert(ST->hasMVEIntegerOps() &&
8845 "CONCAT_VECTORS lowering only supported for MVE");
8848 EVT Op1VT =
V1.getValueType();
8849 EVT Op2VT = V2.getValueType();
8850 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8851 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8852 "Unexpected i1 concat operations!");
8865 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8870 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8879 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8880 EVT NewVT = NewV.getValueType();
8881 EVT ConcatVT = ConVec.getValueType();
8882 unsigned ExtScale = 1;
8883 if (NewVT == MVT::v2f64) {
8884 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8897 ConVec = ExtractInto(NewV1, ConVec, j);
8898 ConVec = ExtractInto(NewV2, ConVec, j);
8902 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8908 while (ConcatOps.
size() > 1) {
8909 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8912 ConcatOps[
I / 2] = ConcatPair(
V1, V2);
8916 return ConcatOps[0];
8921 EVT VT =
Op->getValueType(0);
8927 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
8928 "unexpected CONCAT_VECTORS");
8949 EVT VT =
Op.getValueType();
8950 EVT Op1VT =
V1.getValueType();
8955 "Unexpected custom EXTRACT_SUBVECTOR lowering");
8956 assert(ST->hasMVEIntegerOps() &&
8957 "EXTRACT_SUBVECTOR lowering only supported for MVE");
8967 EVT SubVT = MVT::v4i32;
8969 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
8979 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8984 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
8993 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9000 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9001 EVT VT =
N->getValueType(0);
9002 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9003 "Expected a vector i1 type!");
9005 EVT FromVT =
Op.getValueType();
9016 if (!Subtarget->hasMVEIntegerOps())
9019 EVT ToVT =
N->getValueType(0);
9062 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9064 EVT FromVT =
N->getOperand(0).getValueType();
9065 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9076 if (!Subtarget->hasMVEIntegerOps())
9081 EVT ToVT =
N->getValueType(0);
9082 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9085 EVT FromVT =
Op.getValueType();
9086 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9100 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9101 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9113 EVT VT =
N->getValueType(0);
9115 SDNode *BVN =
N->getOperand(0).getNode();
9120 unsigned HiElt = 1 - LoElt;
9125 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9141 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9142 SDNode *Elt =
N->getOperand(i).getNode();
9145 unsigned HalfSize = EltSize / 2;
9147 if (!
isIntN(HalfSize,
C->getSExtValue()))
9150 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9189 switch (OrigSimpleTy) {
9205 unsigned ExtOpcode) {
9228 if (ExtendedTy == LD->getMemoryVT())
9229 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9230 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9231 LD->getMemOperand()->getFlags());
9237 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9238 LD->getMemoryVT(), LD->getAlign(),
9239 LD->getMemOperand()->getFlags());
9252 N->getOperand(0)->getValueType(0),
9258 "Expected extending load");
9264 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9273 SDNode *BVN =
N->getOperand(0).getNode();
9275 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9283 EVT VT =
N->getValueType(0);
9289 for (
unsigned i = 0; i != NumElts; ++i) {
9290 const APInt &CInt =
N->getConstantOperandAPInt(i);
9299 unsigned Opcode =
N->getOpcode();
9301 SDNode *N0 =
N->getOperand(0).getNode();
9302 SDNode *N1 =
N->getOperand(1).getNode();
9310 unsigned Opcode =
N->getOpcode();
9312 SDNode *N0 =
N->getOperand(0).getNode();
9313 SDNode *N1 =
N->getOperand(1).getNode();
9323 EVT VT =
Op.getValueType();
9325 "unexpected type for custom-lowering ISD::MUL");
9326 SDNode *N0 =
Op.getOperand(0).getNode();
9327 SDNode *N1 =
Op.getOperand(1).getNode();
9328 unsigned NewOpc = 0;
9332 if (isN0SExt && isN1SExt)
9333 NewOpc = ARMISD::VMULLs;
9337 if (isN0ZExt && isN1ZExt)
9338 NewOpc = ARMISD::VMULLu;
9339 else if (isN1SExt || isN1ZExt) {
9343 NewOpc = ARMISD::VMULLs;
9346 NewOpc = ARMISD::VMULLu;
9350 NewOpc = ARMISD::VMULLu;
9356 if (VT == MVT::v2i64)
9373 "unexpected types for extended operands to VMULL");
9374 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9409 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9443 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9446 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9467 EVT VT =
Op.getValueType();
9468 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9469 "unexpected type for custom-lowering ISD::SDIV");
9476 if (VT == MVT::v8i8) {
9504 EVT VT =
Op.getValueType();
9505 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9506 "unexpected type for custom-lowering ISD::UDIV");
9513 if (VT == MVT::v8i8) {
9552 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9555 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9559 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9579 unsigned Opcode,
bool IsSigned) {
9580 EVT VT0 =
Op.getValue(0).getValueType();
9581 EVT VT1 =
Op.getValue(1).getValueType();
9583 bool InvertCarry = Opcode == ARMISD::SUBE;
9603 EVT VT =
Op.getValueType();
9604 assert((VT == MVT::i32 || VT == MVT::i64) &&
9605 "unexpected type for custom lowering DIV");
9611 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9613 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9620 for (
auto AI : {1, 0}) {
9621 SDValue Operand =
Op.getOperand(AI);
9622 Args.emplace_back(Operand,
9639ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9647 const bool MinSize =
ST.hasMinSize();
9648 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9649 :
ST.hasDivideInARMMode();
9653 if (
N->getOperand(0).getValueType().isVector())
9658 if (!(MinSize && HasDivide))
9665 return SDValue(
N, 0);
9671 if (Divisor.
sgt(128))
9674 return SDValue(
N, 0);
9679 assert(
Op.getValueType() == MVT::i32 &&
9680 "unexpected type for custom lowering DIV");
9683 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9686 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9692 if (
N->getValueType(0) == MVT::i32)
9693 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9696 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9700void ARMTargetLowering::ExpandDIV_Windows(
9705 assert(
Op.getValueType() == MVT::i64 &&
9706 "unexpected type for custom lowering DIV");
9711 SDValue
Result = LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9721std::pair<SDValue, SDValue>
9722ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9728 EVT MemVT =
LD->getMemoryVT();
9729 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9730 return std::make_pair(SDValue(), SDValue());
9733 unsigned AS =
LD->getAddressSpace();
9736 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9738 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9746 Opts, dl,
LD->getChain());
9753 SDValue EN = DAG.
getNode(ExtType, dl,
LD->getValueType(0), Pair.first);
9762 return std::make_pair(SDValue(), SDValue());
9771 EVT MemVT =
ST->getMemoryVT();
9772 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9776 unsigned AS =
ST->getAddressSpace();
9779 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9781 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9789 SDValue StoreVal =
ST->getOperand(1);
9790 if (
ST->isTruncatingStore())
9795 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9796 dl,
ST->getChain());
9798 return CallResult.second;
9809 EVT MemVT = LD->getMemoryVT();
9810 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9811 MemVT == MVT::v16i1) &&
9812 "Expected a predicate type!");
9813 assert(MemVT ==
Op.getValueType());
9815 "Expected a non-extending load");
9816 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9830 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9832 LD->getMemOperand());
9838 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9839 if (MemVT != MVT::v16i1)
9848 EVT MemVT =
LD->getMemoryVT();
9850 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9851 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9852 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9853 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9856 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9857 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9862 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9863 auto Pair = LowerAEABIUnalignedLoad(SDValue(
N, 0), DAG);
9865 Results.push_back(Pair.first);
9866 Results.push_back(Pair.second);
9873 EVT MemVT = ST->getMemoryVT();
9874 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9875 MemVT == MVT::v16i1) &&
9876 "Expected a predicate type!");
9877 assert(MemVT == ST->getValue().getValueType());
9878 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9879 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9884 SDValue Build = ST->getValue();
9885 if (MemVT != MVT::v16i1) {
9898 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9904 ST->getChain(), dl, GRP, ST->getBasePtr(),
9906 ST->getMemOperand());
9912 EVT MemVT =
ST->getMemoryVT();
9914 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9915 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
9916 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9917 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
9918 SDNode *
N =
Op.getNode();
9931 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
9932 MemVT,
ST->getMemOperand());
9933 }
else if (Subtarget->hasMVEIntegerOps() &&
9934 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9935 MemVT == MVT::v16i1))) {
9937 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9938 return LowerAEABIUnalignedStore(
Op, DAG);
9945 (
N->getOpcode() == ARMISD::VMOVIMM &&
9951 MVT VT =
Op.getSimpleValueType();
9953 SDValue PassThru =
N->getPassThru();
9964 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
9965 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
9966 N->getExtensionType(),
N->isExpandingLoad());
9969 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
9971 if (!PassThru.
isUndef() && !PassThruIsCastZero)
9978 if (!ST->hasMVEIntegerOps())
9982 unsigned BaseOpcode = 0;
9983 switch (
Op->getOpcode()) {
9999 unsigned NumActiveLanes = NumElts;
10001 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10002 NumActiveLanes == 2) &&
10003 "Only expected a power 2 vector size");
10007 while (NumActiveLanes > 4) {
10008 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10010 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10011 NumActiveLanes /= 2;
10015 if (NumActiveLanes == 4) {
10025 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10026 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10027 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10033 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10037 if (EltVT !=
Op->getValueType(0))
10044 if (!ST->hasMVEFloatOps())
10051 if (!ST->hasNEON())
10059 unsigned PairwiseIntrinsic = 0;
10060 switch (
Op->getOpcode()) {
10064 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10067 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10070 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10073 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10079 unsigned NumActiveLanes = NumElts;
10081 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10082 NumActiveLanes == 2) &&
10083 "Only expected a power 2 vector size");
10089 VT =
Lo.getValueType();
10091 NumActiveLanes /= 2;
10095 while (NumActiveLanes > 1) {
10097 NumActiveLanes /= 2;
10104 if (EltVT !=
Op.getValueType()) {
10105 unsigned Extend = 0;
10106 switch (
Op->getOpcode()) {
10118 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10158 SDLoc dl(V0.getNode());
10163 const SDValue Ops[] = {RegClass, V0, SubReg0,
V1, SubReg1};
10169 SDLoc dl(V.getNode());
10170 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10180 assert(
N->getValueType(0) == MVT::i64 &&
10181 "AtomicCmpSwap on types less than 64 should be legal");
10190 ARM::CMP_SWAP_64,
SDLoc(
N),
10191 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10210 EVT VT =
Op.getValueType();
10211 SDValue Chain =
Op.getOperand(0);
10212 SDValue
LHS =
Op.getOperand(1);
10213 SDValue
RHS =
Op.getOperand(2);
10219 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10221 Chain, IsSignaling);
10222 if (!
RHS.getNode()) {
10236 SDValue ARMcc = DAG.
getConstant(CondCode, dl, MVT::i32);
10237 SDValue
Cmp = getVFPCmp(
LHS,
RHS, DAG, dl, IsSignaling);
10240 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10241 Result = getCMOV(dl, VT, Result,
True, ARMcc, Cmp, DAG);
10258 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10261 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10267 SDValue
LHS =
Op.getOperand(0);
10268 SDValue
RHS =
Op.getOperand(1);
10274 if (!IsSigned && Subtarget->isThumb1Only()) {
10283 SDValue Sub1WithFlags = DAG.
getNode(
10285 SDValue Sub1Result = Sub1WithFlags.
getValue(0);
10286 SDValue Flags1 = Sub1WithFlags.
getValue(1);
10292 Sub1Result, Sub1Result, Flags1);
10293 SDValue Sbc1Result = Sbc1.
getValue(0);
10302 SDValue Sbc2Result = Sbc2.
getValue(0);
10307 if (
Op.getValueType() != MVT::i32)
10321 unsigned Opcode = ARMISD::SUBC;
10325 SDValue SubLHS =
RHS.getOperand(0);
10326 SDValue SubRHS =
RHS.getOperand(1);
10330 bool CanUseAdd =
false;
10346 Opcode = ARMISD::ADDC;
10354 SDValue OpWithFlags =
10357 SDValue OpResult = OpWithFlags.
getValue(0);
10369 SDValue GTCondValue = DAG.
getConstant(GTCond, dl, MVT::i32);
10370 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10371 GTCondValue, Flags);
10374 SDValue LTCondValue = DAG.
getConstant(LTCond, dl, MVT::i32);
10375 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10376 LTCondValue, Flags);
10378 if (
Op.getValueType() != MVT::i32)
10386 switch (
Op.getOpcode()) {
10420 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10424 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10425 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10447 return LowerSET_FPMODE(
Op, DAG);
10449 return LowerRESET_FPMODE(
Op, DAG);
10453 !
Op.getValueType().isVector())
10454 return LowerDIV_Windows(
Op, DAG,
true);
10458 !
Op.getValueType().isVector())
10459 return LowerDIV_Windows(
Op, DAG,
false);
10475 return LowerALUO(
Op, DAG);
10483 EVT MemVT = LD->getMemoryVT();
10484 if (Subtarget->hasMVEIntegerOps() &&
10485 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10486 MemVT == MVT::v16i1))
10489 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10495 return LowerSTORE(
Op, DAG, Subtarget);
10520 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10529 return LowerSPONENTRY(
Op, DAG);
10531 return LowerFP_TO_BF16(
Op, DAG);
10532 case ARMISD::WIN__DBZCHK:
return SDValue();
10535 return LowerCMP(
Op, DAG);
10537 return LowerABS(
Op, DAG);
10542 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10543 Op.getOperand(1).getValueType() == MVT::bf16) &&
10544 "Expected custom lowering of rounding operations only for f16");
10547 {
Op.getOperand(0),
Op.getOperand(1)});
10548 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10549 {Ext.getValue(1), Ext.getValue(0)});
10556 unsigned IntNo =
N->getConstantOperandVal(0);
10558 if (IntNo == Intrinsic::arm_smlald)
10559 Opc = ARMISD::SMLALD;
10560 else if (IntNo == Intrinsic::arm_smlaldx)
10561 Opc = ARMISD::SMLALDX;
10562 else if (IntNo == Intrinsic::arm_smlsld)
10563 Opc = ARMISD::SMLSLD;
10564 else if (IntNo == Intrinsic::arm_smlsldx)
10565 Opc = ARMISD::SMLSLDX;
10571 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10575 N->getOperand(1),
N->getOperand(2),
10587 switch (
N->getOpcode()) {
10594 Res = ExpandBITCAST(
N, DAG, Subtarget);
10603 Res = LowerREM(
N, DAG);
10607 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10624 "can only expand DIV on Windows");
10636 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10665 "ROPI/RWPI not currently supported with SjLj");
10674 bool isThumb = Subtarget->isThumb();
10675 bool isThumb2 = Subtarget->
isThumb2();
10678 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10684 : &ARM::GPRRegClass;
10702 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10708 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10714 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10732 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10737 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10742 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10747 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10753 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10790 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10798 : &ARM::GPRnopcRegClass;
10802 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10803 unsigned MaxCSNum = 0;
10804 for (MachineBasicBlock &BB : *MF) {
10810 for (MachineInstr &
II : BB) {
10811 if (!
II.isEHLabel())
10814 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10815 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10817 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10818 for (
unsigned Idx : CallSiteIdxs) {
10819 CallSiteNumToLPad[
Idx].push_back(&BB);
10820 MaxCSNum = std::max(MaxCSNum, Idx);
10827 std::vector<MachineBasicBlock*> LPadList;
10828 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10829 LPadList.reserve(CallSiteNumToLPad.
size());
10830 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10831 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10832 for (MachineBasicBlock *
MBB : MBBList) {
10833 LPadList.push_back(
MBB);
10838 assert(!LPadList.empty() &&
10839 "No landing pad destinations for the dispatch jump table!");
10842 MachineJumpTableInfo *JTI =
10849 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10852 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10854 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10857 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10861 MF->insert(MF->end(), DispatchBB);
10862 MF->insert(MF->end(), DispContBB);
10863 MF->insert(MF->end(), TrapBB);
10867 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10869 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10873 MachineInstrBuilder MIB;
10874 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10876 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10886 unsigned NumLPads = LPadList.size();
10887 if (Subtarget->isThumb2()) {
10889 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10895 if (NumLPads < 256) {
10896 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10898 .
addImm(LPadList.size())
10902 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10903 .
addImm(NumLPads & 0xFFFF)
10906 unsigned VReg2 = VReg1;
10907 if ((NumLPads & 0xFFFF0000) != 0) {
10909 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10915 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
10921 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
10927 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
10932 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
10939 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
10943 }
else if (Subtarget->isThumb()) {
10945 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
10951 if (NumLPads < 256) {
10952 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
10957 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10959 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
10962 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
10966 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
10970 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
10976 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
10982 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
10989 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
10994 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11000 MachineMemOperand *JTMMOLd =
11005 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11011 unsigned NewVReg6 = NewVReg5;
11012 if (IsPositionIndependent) {
11014 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11021 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11026 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11032 if (NumLPads < 256) {
11033 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11037 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11039 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11040 .
addImm(NumLPads & 0xFFFF)
11043 unsigned VReg2 = VReg1;
11044 if ((NumLPads & 0xFFFF0000) != 0) {
11046 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11052 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11057 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11059 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11062 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11066 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11071 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11083 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11089 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11093 MachineMemOperand *JTMMOLd =
11097 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11104 if (IsPositionIndependent) {
11105 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11110 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11117 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11118 for (MachineBasicBlock *CurMBB : LPadList) {
11119 if (SeenMBBs.
insert(CurMBB).second)
11126 for (MachineBasicBlock *BB : InvokeBBs) {
11130 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11131 while (!Successors.empty()) {
11132 MachineBasicBlock *SMBB = Successors.pop_back_val();
11134 BB->removeSuccessor(SMBB);
11140 BB->normalizeSuccProbs();
11147 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11148 if (!
II->isCall())
continue;
11150 DenseSet<unsigned> DefRegs;
11152 OI =
II->operands_begin(), OE =
II->operands_end();
11154 if (!OI->isReg())
continue;
11155 DefRegs.
insert(OI->getReg());
11158 MachineInstrBuilder MIB(*MF, &*
II);
11160 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11161 unsigned Reg = SavedRegs[i];
11162 if (Subtarget->isThumb2() &&
11163 !ARM::tGPRRegClass.contains(
Reg) &&
11164 !ARM::hGPRRegClass.contains(
Reg))
11166 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11168 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11180 for (MachineBasicBlock *MBBLPad : MBBLPads)
11181 MBBLPad->setIsEHPad(
false);
11184 MI.eraseFromParent();
11197static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11199 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11200 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11202 return LdSize == 4 ? ARM::tLDRi
11203 : LdSize == 2 ? ARM::tLDRHi
11204 : LdSize == 1 ? ARM::tLDRBi : 0;
11206 return LdSize == 4 ? ARM::t2LDR_POST
11207 : LdSize == 2 ? ARM::t2LDRH_POST
11208 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11209 return LdSize == 4 ? ARM::LDR_POST_IMM
11210 : LdSize == 2 ? ARM::LDRH_POST
11211 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11216static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11218 return StSize == 16 ? ARM::VST1q32wb_fixed
11219 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11221 return StSize == 4 ? ARM::tSTRi
11222 : StSize == 2 ? ARM::tSTRHi
11223 : StSize == 1 ? ARM::tSTRBi : 0;
11225 return StSize == 4 ? ARM::t2STR_POST
11226 : StSize == 2 ? ARM::t2STRH_POST
11227 : StSize == 1 ? ARM::t2STRB_POST : 0;
11228 return StSize == 4 ? ARM::STR_POST_IMM
11229 : StSize == 2 ? ARM::STRH_POST
11230 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11237 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11238 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11239 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11240 assert(LdOpc != 0 &&
"Should have a load opcode");
11247 }
else if (IsThumb1) {
11253 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11258 }
else if (IsThumb2) {
11278 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11279 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11280 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11281 assert(StOpc != 0 &&
"Should have a store opcode");
11283 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11288 }
else if (IsThumb1) {
11295 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11300 }
else if (IsThumb2) {
11301 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11307 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11322 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11328 unsigned SizeVal =
MI.getOperand(2).getImm();
11334 unsigned UnitSize = 0;
11338 bool IsThumb1 = Subtarget->isThumb1Only();
11339 bool IsThumb2 = Subtarget->isThumb2();
11340 bool IsThumb = Subtarget->isThumb();
11342 if (Alignment & 1) {
11344 }
else if (Alignment & 2) {
11349 Subtarget->hasNEON()) {
11350 if ((Alignment % 16 == 0) && SizeVal >= 16)
11352 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11361 bool IsNeon = UnitSize >= 8;
11362 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11364 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11365 : UnitSize == 8 ? &ARM::DPRRegClass
11368 unsigned BytesLeft = SizeVal % UnitSize;
11369 unsigned LoopSize = SizeVal - BytesLeft;
11371 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11375 unsigned srcIn = src;
11376 unsigned destIn = dest;
11377 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11382 IsThumb1, IsThumb2);
11384 IsThumb1, IsThumb2);
11392 for (
unsigned i = 0; i < BytesLeft; i++) {
11397 IsThumb1, IsThumb2);
11399 IsThumb1, IsThumb2);
11403 MI.eraseFromParent();
11429 MF->
insert(It, loopMBB);
11430 MF->
insert(It, exitMBB);
11433 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11444 if (Subtarget->useMovt()) {
11445 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11448 }
else if (Subtarget->genExecuteOnly()) {
11449 assert(IsThumb &&
"Non-thumb expected to have used movt");
11454 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11459 MachineMemOperand *CPMMO =
11483 MachineBasicBlock *entryBB = BB;
11498 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11506 IsThumb1, IsThumb2);
11508 IsThumb1, IsThumb2);
11512 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11518 MachineInstrBuilder MIB =
11520 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11529 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11538 auto StartOfExit = exitMBB->
begin();
11542 unsigned srcIn = srcLoop;
11543 unsigned destIn = destLoop;
11544 for (
unsigned i = 0; i < BytesLeft; i++) {
11548 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11549 IsThumb1, IsThumb2);
11550 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11551 IsThumb1, IsThumb2);
11556 MI.eraseFromParent();
11564 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11567 assert(TM.getTargetTriple().isOSWindows() &&
11568 "__chkstk is only supported on Windows");
11569 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11589 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11590 if (ChkStkLibcall == RTLIB::Unsupported)
11594 switch (TM.getCodeModel()) {
11638 MI.eraseFromParent();
11647 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11662 .
addReg(
MI.getOperand(0).getReg())
11670 MI.eraseFromParent();
11694 if (miI == BB->
end()) {
11696 if (Succ->isLiveIn(ARM::CPSR))
11702 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11714 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11715 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11721 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11722 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11728 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11729 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11732 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11733 .
addUse(TotalIterationsReg)
11740 return TotalIterationsReg;
11751 Register TotalIterationsReg,
bool IsMemcpy) {
11758 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11759 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11760 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11768 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11769 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11770 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11777 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11778 Register RemainingLoopIterationsReg =
11779 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11780 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11781 .
addUse(TotalIterationsReg)
11783 .
addUse(RemainingLoopIterationsReg)
11787 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11788 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11789 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11790 .
addUse(ElementCountReg)
11792 .
addUse(RemainingElementsReg)
11796 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11797 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11798 .
addUse(PredCounterPhiReg)
11803 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11804 .
addUse(PredCounterPhiReg)
11812 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11813 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11822 SrcValueReg = OpSrcReg;
11824 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11835 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11836 .
addUse(LoopCounterPhiReg)
11839 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11840 .
addUse(RemainingLoopIterationsReg)
11858 "Invalid call instruction for a KCFI check");
11861 switch (
MBBI->getOpcode()) {
11864 case ARM::BLX_pred:
11865 case ARM::BLX_noip:
11866 case ARM::BLX_pred_noip:
11868 TargetOp = &
MBBI->getOperand(0);
11870 case ARM::TCRETURNri:
11871 case ARM::TCRETURNrinotr12:
11872 case ARM::TAILJMPr:
11873 case ARM::TAILJMPr4:
11874 TargetOp = &
MBBI->getOperand(0);
11880 case ARM::tBLXr_noip:
11881 case ARM::tBX_CALL:
11882 TargetOp = &
MBBI->getOperand(2);
11885 case ARM::tTAILJMPr:
11886 TargetOp = &
MBBI->getOperand(0);
11892 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11896 unsigned KCFICheckOpcode;
11897 if (Subtarget->isThumb()) {
11898 if (Subtarget->isThumb2()) {
11899 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11901 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11904 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11918 bool isThumb2 = Subtarget->isThumb2();
11919 switch (
MI.getOpcode()) {
11926 case ARM::tLDR_postidx: {
11930 .
add(
MI.getOperand(2))
11931 .
add(
MI.getOperand(3))
11932 .
add(
MI.getOperand(4))
11933 .
add(
MI.getOperand(0))
11935 MI.eraseFromParent();
11939 case ARM::MVE_MEMCPYLOOPINST:
11940 case ARM::MVE_MEMSETLOOPINST: {
11970 Register OpDestReg =
MI.getOperand(0).getReg();
11971 Register OpSrcReg =
MI.getOperand(1).getReg();
11972 Register OpSizeReg =
MI.getOperand(2).getReg();
11992 if (TpExit == BB) {
11994 "block containing memcpy/memset Pseudo");
12007 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12009 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12012 Properties.resetNoPHIs();
12024 MI.eraseFromParent();
12034 case ARM::t2STR_preidx:
12035 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12037 case ARM::t2STRB_preidx:
12038 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12040 case ARM::t2STRH_preidx:
12041 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12044 case ARM::STRi_preidx:
12045 case ARM::STRBi_preidx: {
12046 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12047 : ARM::STRB_PRE_IMM;
12049 unsigned Offset =
MI.getOperand(4).getImm();
12057 .
add(
MI.getOperand(0))
12058 .
add(
MI.getOperand(1))
12059 .
add(
MI.getOperand(2))
12061 .
add(
MI.getOperand(5))
12062 .
add(
MI.getOperand(6))
12064 MI.eraseFromParent();
12067 case ARM::STRr_preidx:
12068 case ARM::STRBr_preidx:
12069 case ARM::STRH_preidx: {
12071 switch (
MI.getOpcode()) {
12073 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12074 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12075 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12080 MI.eraseFromParent();
12084 case ARM::tMOVCCr_pseudo: {
12102 F->insert(It, copy0MBB);
12103 F->insert(It, sinkMBB);
12106 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12112 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12128 .
addImm(
MI.getOperand(3).getImm())
12129 .
addReg(
MI.getOperand(4).getReg());
12144 .
addReg(
MI.getOperand(1).getReg())
12146 .
addReg(
MI.getOperand(2).getReg())
12149 MI.eraseFromParent();
12154 case ARM::BCCZi64: {
12160 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12165 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12169 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12175 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12179 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12189 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12198 MI.eraseFromParent();
12202 case ARM::Int_eh_sjlj_setjmp:
12203 case ARM::Int_eh_sjlj_setjmp_nofp:
12204 case ARM::tInt_eh_sjlj_setjmp:
12205 case ARM::t2Int_eh_sjlj_setjmp:
12206 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12209 case ARM::Int_eh_sjlj_setup_dispatch:
12210 EmitSjLjDispatchBlock(
MI, BB);
12212 case ARM::COPY_STRUCT_BYVAL_I32:
12214 return EmitStructByval(
MI, BB);
12215 case ARM::WIN__CHKSTK:
12216 return EmitLowered__chkstk(
MI, BB);
12217 case ARM::WIN__DBZCHK:
12218 return EmitLowered__dbzchk(
MI, BB);
12234 if (!
Node->hasAnyUseOfValue(0)) {
12235 MI.getOperand(0).setIsDead(
true);
12237 if (!
Node->hasAnyUseOfValue(1)) {
12238 MI.getOperand(1).setIsDead(
true);
12242 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12243 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12244 : &ARM::GPRRegClass);
12251 if (
MI.getOpcode() == ARM::MEMCPY) {
12272 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12273 &&
"converted opcode should be the same except for cc_out"
12274 " (and, on Thumb1, pred)");
12282 if (Subtarget->isThumb1Only()) {
12283 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12284 MI.addOperand(
MI.getOperand(1));
12285 MI.removeOperand(1);
12289 for (
unsigned i =
MI.getNumOperands(); i--;) {
12291 if (
op.isReg() &&
op.isUse()) {
12294 MI.tieOperands(DefIdx, i);
12302 ccOutIdx =
MCID->getNumOperands() - 1;
12304 ccOutIdx =
MCID->getNumOperands() - 1;
12308 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12309 assert(!NewOpc &&
"Optional cc_out operand required");
12315 bool deadCPSR =
false;
12316 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12323 MI.removeOperand(i);
12328 assert(!NewOpc &&
"Optional cc_out operand required");
12331 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12333 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12334 "expect uninitialized optional cc_out operand");
12336 if (!Subtarget->isThumb1Only())
12373 switch (
N->getOpcode()) {
12374 default:
return false;
12376 CC =
N->getOperand(0);
12398 EVT VT =
N->getValueType(0);
12399 CC =
N->getOperand(0);
12400 if (
CC.getValueType() != MVT::i1 ||
CC.getOpcode() !=
ISD::SETCC)
12446 EVT VT =
N->getValueType(0);
12449 bool SwapSelectOps;
12451 NonConstantVal, DAG))
12457 OtherOp, NonConstantVal);
12463 CCOp, TrueVal, FalseVal);
12483 if (
N->getOpcode() == ARMISD::VUZP)
12487 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12502 if (!
N->getValueType(0).is64BitVector())
12510 EVT VT =
N->getValueType(0);
12549 EVT VT =
N->getValueType(0);
12555 Opcode = Intrinsic::arm_neon_vpaddls;
12557 Opcode = Intrinsic::arm_neon_vpaddlu;
12585 EVT VT =
N->getValueType(0);
12600 unsigned nextIndex = 0;
12622 if (!
C0 || !
C1 ||
C0->getZExtValue() != nextIndex
12623 ||
C1->getZExtValue() != nextIndex+1)
12651 Ops.push_back(Vec);
12668 return DAG.
getNode(ExtOp, dl, VT, tmp);
12699 if (SRA.getOpcode() !=
ISD::SRA) {
12706 if (Const->getZExtValue() != 31)
12711 if (SRA.getOperand(0) !=
Mul)
12715 SDLoc dl(AddcNode);
12716 unsigned Opcode = 0;
12721 Opcode = ARMISD::SMLALBB;
12722 Op0 =
Mul.getOperand(0);
12723 Op1 =
Mul.getOperand(1);
12725 Opcode = ARMISD::SMLALBT;
12726 Op0 =
Mul.getOperand(0);
12727 Op1 =
Mul.getOperand(1).getOperand(0);
12729 Opcode = ARMISD::SMLALTB;
12730 Op0 =
Mul.getOperand(0).getOperand(0);
12731 Op1 =
Mul.getOperand(1);
12733 Opcode = ARMISD::SMLALTT;
12734 Op0 =
Mul->getOperand(0).getOperand(0);
12735 Op1 =
Mul->getOperand(1).getOperand(0);
12779 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12780 "Expect an ADDE or SUBE");
12784 "ADDE node has the wrong inputs");
12791 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12792 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12793 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12794 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12806 "Expect ADDC with two result values. First: i32");
12810 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12826 bool IsLeftOperandMUL =
false;
12831 IsLeftOperandMUL =
true;
12842 SDValue *LowAddSub =
nullptr;
12845 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12848 if (IsLeftOperandMUL)
12849 HiAddSub = &AddeSubeOp1;
12851 HiAddSub = &AddeSubeOp0;
12856 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12857 LoMul = &AddcSubcOp0;
12858 LowAddSub = &AddcSubcOp1;
12860 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12861 LoMul = &AddcSubcOp1;
12862 LowAddSub = &AddcSubcOp0;
12870 if (AddcSubcNode == HiAddSub->getNode() ||
12886 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12887 FinalOpc == ARMISD::SMLAL &&
12891 Ops.push_back(*HiAddSub);
12892 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12893 FinalOpc = ARMISD::SMMLSR;
12895 FinalOpc = ARMISD::SMMLAR;
12900 return SDValue(AddeSubeNode, 0);
12901 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12907 Ops.push_back(*LowAddSub);
12908 Ops.push_back(*HiAddSub);
12921 return SDValue(AddeSubeNode, 0);
12936 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12941 if (AddcNode->
getOpcode() != ARMISD::ADDC)
12945 SDNode *UmlalNode =
nullptr;
12984 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12989 SDNode* AddcNode =
N->getOperand(2).getNode();
12990 SDNode* AddeNode =
N->getOperand(3).getNode();
12991 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
12992 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
12998 {N->getOperand(0), N->getOperand(1),
12999 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13009 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13013 if (
LHS->getOpcode() == ARMISD::ADDE &&
13023 int32_t imm =
C->getSExtValue();
13024 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13027 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13029 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13044 int64_t imm =
C->getSExtValue();
13053 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13055 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13056 N->getOperand(0),
RHS,
N->getOperand(2));
13068 if (!Subtarget->hasMVEIntegerOps())
13081 SetCC =
N->getOperand(0);
13085 TrueVal =
N->getOperand(1);
13086 FalseVal =
N->getOperand(2);
13088 LHS =
N->getOperand(0);
13089 RHS =
N->getOperand(1);
13091 TrueVal =
N->getOperand(2);
13092 FalseVal =
N->getOperand(3);
13097 unsigned int Opcode = 0;
13101 Opcode = ARMISD::VMINVu;
13107 Opcode = ARMISD::VMINVs;
13113 Opcode = ARMISD::VMAXVu;
13119 Opcode = ARMISD::VMAXVs;
13126 switch (TrueVal->getOpcode()) {
13145 if (TrueVal !=
LHS || FalseVal !=
RHS)
13148 EVT LeftType =
LHS->getValueType(0);
13149 EVT RightType =
RHS->getValueType(0);
13152 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13156 if (VectorScalarType != MVT::i32)
13164 if (VectorScalarType != MVT::i32)
13177 EVT VT =
N->getValueType(0);
13185 Shft =
N->getOperand(0);
13192 Cmp.getOperand(0) !=
N->getOperand(1) ||
13193 Cmp.getOperand(1) !=
N->getOperand(2))
13195 Shft =
N->getOperand(1);
13207 ScalarType = MVT::i8;
13210 case (1 << 15) - 1:
13211 ScalarType = MVT::i16;
13214 case (1ULL << 31) - 1:
13215 ScalarType = MVT::i32;
13246 unsigned LegalLanes = 128 / (ShftAmt + 1);
13258 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13259 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13260 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13261 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13270 for (
unsigned I = 0;
I < NumParts; ++
I) {
13277 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13287 if (!Subtarget->hasMVEIntegerOps())
13292 if (
N->getOperand(0).getOpcode() == ARMISD::PREDICATE_CAST &&
13294 unsigned C =
N->getOperand(0).getConstantOperandVal(0);
13296 return N->getOperand(2);
13298 return N->getOperand(1);
13313 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13323 if (!Const || !Const->isOne())
13341 EVT VT =
N->getValueType(0);
13343 if (!Subtarget->hasMVEIntegerOps() ||
13372 Opc = Intrinsic::arm_mve_vctp32;
13375 Opc = Intrinsic::arm_mve_vctp16;
13378 Opc = Intrinsic::arm_mve_vctp8;
13432 EVT VT =
N->getValueType(0);
13438 switch (
Op.getOpcode()) {
13440 case ARMISD::VADDVs:
13441 case ARMISD::VADDVu:
13442 case ARMISD::VMLAVs:
13443 case ARMISD::VMLAVu:
13463 unsigned N0RedOp = 0;
13470 unsigned N1RedOp = 0;
13484 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13486 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13493 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13517 if (!BaseLocDecomp0.getBase() ||
13518 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13519 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13521 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13523 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13533 if (IsBefore < 0) {
13536 }
else if (IsBefore > 0) {
13549 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13559 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13569 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13571 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13578 if (!Subtarget->hasMVEIntegerOps())
13584 EVT VT =
N->getValueType(0);
13589 if (VT != MVT::i64)
13600 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13620 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13629 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13631 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13633 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13635 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13637 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13639 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13641 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13643 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13645 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13647 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13649 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13651 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13653 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13655 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13657 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13659 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13669 "Expected shift op");
13671 SDValue ShiftLHS =
N->getOperand(0);
13685 if (Subtarget->isThumb1Only()) {
13696 if (Const->getAPIntValue().ult(256))
13699 Const->getAPIntValue().sgt(-256))
13715 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13716 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13717 "Expected XOR(SHIFT) pattern");
13722 if (XorC && ShiftC) {
13723 unsigned MaskIdx, MaskLen;
13724 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13725 unsigned ShiftAmt = ShiftC->getZExtValue();
13726 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13727 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13728 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13729 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13739 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13741 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13742 "Expected shift-shift mask");
13744 if (!Subtarget->isThumb1Only())
13747 EVT VT =
N->getValueType(0);
13755 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13757 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13762 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps()) {
13763 if (Subtarget->isThumb1Only())
13777 return Subtarget->hasVFP2Base();
13779 return Subtarget->hasVFP2Base();
13781 return Subtarget->hasFP64();
13784 return Subtarget->hasMVEFloatOps();
13813 if (ST->isThumb1Only())
13817 for (
auto *U :
N->users()) {
13818 switch(U->getOpcode()) {
13836 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13837 U->getOperand(1).getOpcode() ==
ISD::SHL)
13847 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13854 if (!C1ShlC2 || !C2)
13857 APInt C2Int = C2->getAPIntValue();
13858 APInt C1Int = C1ShlC2->getAPIntValue();
13860 if (C2Int.
uge(C2Width))
13866 if ((C1Int & Mask) != C1Int)
13873 auto LargeImm = [](
const APInt &
Imm) {
13874 unsigned Zeros =
Imm.countl_zero() +
Imm.countr_zero();
13875 return Imm.getBitWidth() - Zeros > 8;
13878 if (LargeImm(C1Int) || LargeImm(C2Int))
13890 SHL.dump();
N->dump());
13951 if (
Op.hasOneUse() && ShiftAmt &&
13952 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
14010 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14031 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14052 if (!Subtarget->hasVMLxForwarding())
14071 EVT VT =
N->getValueType(0);
14082 EVT VT =
N->getValueType(0);
14083 if (VT != MVT::v2i64)
14094 return Op->getOperand(0);
14108 And =
And->getOperand(0);
14113 Mask = Mask->getOperand(0);
14116 Mask.getValueType() != MVT::v4i32)
14122 return And->getOperand(0);
14127 if (
SDValue Op0 = IsSignExt(N0)) {
14128 if (
SDValue Op1 = IsSignExt(N1)) {
14129 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14130 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14131 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14134 if (
SDValue Op0 = IsZeroExt(N0)) {
14135 if (
SDValue Op1 = IsZeroExt(N1)) {
14136 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14137 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14138 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14150 EVT VT =
N->getValueType(0);
14151 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14162 if (VT != MVT::i32)
14169 int64_t MulAmt =
C->getSExtValue();
14172 ShiftAmt = ShiftAmt & (32 - 1);
14177 MulAmt >>= ShiftAmt;
14238 if (
N->getValueType(0) != MVT::i32)
14247 if (
C1 == 255 ||
C1 == 65535)
14250 SDNode *N0 =
N->getOperand(0).getNode();
14264 if (!C2 || C2 >= 32)
14308 if (Trailing == C2 && C2 + C3 < 32) {
14321 if (Leading == C2 && C2 + C3 < 32) {
14349 EVT VT =
N->getValueType(0);
14353 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14356 APInt SplatBits, SplatUndef;
14357 unsigned SplatBitSize;
14359 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14360 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14361 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14362 SplatBitSize == 64) {
14369 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14371 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14396 if (!Subtarget->hasV6Ops() ||
14397 (Subtarget->isThumb() &&
14398 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14401 SDValue SRL = OR->getOperand(0);
14402 SDValue SHL = OR->getOperand(1);
14405 SRL = OR->getOperand(1);
14406 SHL = OR->getOperand(0);
14413 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14417 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14418 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14419 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14438 unsigned Opcode = 0;
14439 if (
isS16(OpS16, DAG))
14440 Opcode = ARMISD::SMULWB;
14442 Opcode = ARMISD::SMULWT;
14457 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14460 EVT VT =
N->getValueType(0);
14475 if (VT != MVT::i32)
14488 if (Mask == 0xffff)
14495 if ((Val & ~Mask) != Val)
14501 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14520 (Mask == ~Mask2)) {
14523 if (Subtarget->hasDSP() &&
14524 (Mask == 0xffff || Mask == 0xffff0000))
14530 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14537 (~Mask == Mask2)) {
14540 if (Subtarget->hasDSP() &&
14541 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14597 if (
N->getOpcode() == ARMISD::VCMP)
14599 else if (
N->getOpcode() == ARMISD::VCMPZ)
14614 EVT VT =
N->getValueType(0);
14619 auto IsFreelyInvertable = [&](
SDValue V) {
14620 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14626 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14644 if (AndOp.getOpcode() !=
ISD::AND)
14648 SDValue Mask = AndOp.getOperand(1);
14658 bool IsShiftRight =
false;
14661 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14662 IsShiftRight =
true;
14665 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14673 APInt RequiredMask = IsShiftRight
14676 if (MaskBits != RequiredMask)
14679 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14689 EVT VT =
N->getValueType(0);
14695 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14696 VT == MVT::v8i1 || VT == MVT::v16i1))
14699 APInt SplatBits, SplatUndef;
14700 unsigned SplatBitSize;
14702 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14703 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14704 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14705 SplatBitSize == 64) {
14712 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14714 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14734 (Subtarget->hasMVEIntegerOps() &&
14735 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14738 return ShiftInsert;
14742 return ShiftInsert;
14756 unsigned SplatBitSize;
14759 APInt SplatBits0, SplatBits1;
14763 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14764 HasAnyUndefs) && !HasAnyUndefs) {
14765 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14766 HasAnyUndefs) && !HasAnyUndefs) {
14771 SplatBits0 == ~SplatBits1) {
14782 DAG.
getNode(ARMISD::VBSP, dl, CanonicalVT, Mask,
LHS,
RHS);
14783 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14803 if (CSINC.
getOpcode() != ARMISD::CSINC)
14805 if (CSINC.
getOpcode() == ARMISD::CSINC &&
14818 EVT VT =
N->getValueType(0);
14833 if (Subtarget->hasMVEIntegerOps()) {
14861 assert(
N->getOpcode() == ARMISD::BFI);
14864 ToMask =
~N->getConstantOperandAPInt(2);
14884 unsigned LastActiveBitInA =
A.countr_zero();
14885 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14886 return LastActiveBitInA - 1 == FirstActiveBitInB;
14891 APInt ToMask, FromMask;
14896 if (V.getOpcode() != ARMISD::BFI)
14899 APInt NewToMask, NewFromMask;
14901 if (NewFrom != From)
14905 if ((NewToMask & ToMask).getBoolValue())
14930 unsigned InvMask =
N->getConstantOperandVal(2);
14934 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14935 "undefined behavior");
14936 unsigned Mask = (1u << Width) - 1;
14938 if ((Mask & (~Mask2)) == 0)
14940 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14947 APInt ToMask1, FromMask1;
14950 APInt ToMask2, FromMask2;
14956 APInt NewFromMask = FromMask1 | FromMask2;
14957 APInt NewToMask = ToMask1 | ToMask2;
14959 EVT VT =
N->getValueType(0);
14962 if (NewFromMask[0] == 0)
14965 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
14973 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
14974 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14975 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14977 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14981 EVT VT =
N->getValueType(0);
14984 N->getOperand(1),
N->getOperand(2));
14996 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
14998 SDValue CSInc = Cmp->getOperand(0);
15008 if (CSInc.
getOpcode() == ARMISD::CSINC &&
15048 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15049 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15052 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15054 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15067 SDValue InDouble =
N->getOperand(0);
15068 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15082 SDValue BasePtr = LD->getBasePtr();
15084 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15085 LD->getAlign(), LD->getMemOperand()->getFlags());
15091 LD->getPointerInfo().getWithOffset(4),
15093 LD->getMemOperand()->getFlags());
15112 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15126 if (!Subtarget->
isLittle() && BVSwap)
15144 if (!Subtarget->
isLittle() && BVSwap)
15163 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15176 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15189 if (Copy.getValueType() == MVT::f32 &&
15191 bool HasGlue = Copy->getNumOperands() == 3;
15192 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15193 HasGlue ? Copy->getOperand(2) :
SDValue()};
15194 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15213 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15214 LN0->getMemoryVT() == MVT::i16) {
15217 LN0->getBasePtr(), LN0->getMemOperand());
15235 EVT VT =
N->getValueType(0);
15269 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15270 for (
unsigned i = 0; i < NumElts; ++i) {
15271 SDNode *Elt =
N->getOperand(i).getNode();
15288 if (
N->getNumOperands() == 2)
15294 EVT VT =
N->getValueType(0);
15300 for (
unsigned i = 0; i < NumElts; ++i) {
15319 unsigned NumParts =
N->getNumOperands();
15320 if (NumParts < 2 || NumParts > 4)
15323 if (NumParts == 3 && Subtarget->hasMVEIntegerOps())
15326 EVT SubVecTy =
N->getValueType(0);
15330 if (Subtarget->hasMVEIntegerOps() && !SubVecTy.
is128BitVector())
15333 if (EltBits != 8 && EltBits != 16 && EltBits != 32)
15337 for (
const SDValue &Operand :
N->op_values()) {
15345 if (Subtarget->hasMVEIntegerOps() && BaseLoad->
getAlign() < EltBits / 8)
15367 static constexpr Intrinsic::ID NEONLoads[] = {Intrinsic::arm_neon_vld2,
15368 Intrinsic::arm_neon_vld3,
15369 Intrinsic::arm_neon_vld4};
15370 if (Subtarget->hasNEON())
15371 IID = NEONLoads[NumParts - 2];
15373 IID = NumParts == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
15382 for (
unsigned I = 0;
I != NumParts; ++
I)
15398 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
15409 unsigned NumParts =
N->getNumOperands();
15410 if (NumParts != 2 && NumParts != 3 && NumParts != 4)
15413 if (NumParts == 3 && Subtarget->hasMVEIntegerOps())
15416 EVT SubVecTy =
N->getValueType(0);
15421 if (Subtarget->hasMVEIntegerOps() && !SubVecTy.
is128BitVector())
15424 if (EltBits != 8 && EltBits != 16 && EltBits != 32)
15431 for (
unsigned I = 0;
I < NumParts;
I++) {
15447 if (!
Load || !
Load->hasNUsesOfValue(NumParts, 0) || !
Load->isSimple() ||
15450 if (Subtarget->hasMVEIntegerOps() &&
Load->getAlign() < EltBits / 8)
15453 static constexpr Intrinsic::ID NEONLoads[] = {Intrinsic::arm_neon_vld2,
15454 Intrinsic::arm_neon_vld3,
15455 Intrinsic::arm_neon_vld4};
15459 if (Subtarget->hasNEON())
15460 IID = NEONLoads[NumParts - 2];
15462 IID = NumParts == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
15470 Load->getMemoryVT(),
Load->getMemOperand());
15473 for (
unsigned Idx = 0; Idx < NumParts; Idx++)
15485 EVT VT =
N->getValueType(0);
15491 auto IsExtractFromBuildVec = [](
SDValue V,
SDValue &BV, int64_t &Lane) {
15495 BV = BV.getOperand(0);
15497 BV.getNumOperands() == 4 &&
15498 BV.getValueType().getScalarSizeInBits() == 32;
15501 int64_t Lane1, Lane2;
15502 if (IsExtractFromBuildVec(
N->getOperand(0), BV1, Lane1) &&
15503 IsExtractFromBuildVec(
N->getOperand(1), BV2, Lane2))
15532 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15537 Use->getValueType(0).isFloatingPoint())
15545 unsigned NumOfBitCastedElts = 0;
15547 unsigned NumOfRelevantElts = NumElts;
15548 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15553 ++NumOfBitCastedElts;
15557 --NumOfRelevantElts;
15561 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15578 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15583 V->getOperand(0).getValueType() == MVT::i32)
15585 V = V.getOperand(0);
15602 EVT VT =
N->getValueType(0);
15607 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15609 if (
Op->getOperand(0).getValueType() == VT)
15610 return Op->getOperand(0);
15611 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15618 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15625 if (
Op.getValueType() == MVT::i32) {
15636 EVT VT =
N->getValueType(0);
15641 if (ST->isLittle())
15645 if (
Op.getValueType() == VT)
15652 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15654 if (
Op->getOperand(0).getValueType() == VT)
15655 return Op->getOperand(0);
15656 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15664 if (!Subtarget->hasMVEIntegerOps())
15667 EVT VT =
N->getValueType(0);
15675 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15681 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15685 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15698 EVT VT =
N->getValueType(0);
15699 SDNode *Elt =
N->getOperand(1).getNode();
15714 Vec, V,
N->getOperand(2));
15724 EVT VT =
N->getValueType(0);
15752 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15753 isa<ConstantSDNode>(V->getOperand(1)) &&
15754 V->getConstantOperandVal(1) == Lane + 1 &&
15755 V->getOperand(0).getResNo() == ResNo;
15757 if (OtherIt == Op0->
users().
end())
15762 SDValue OtherExt(*OtherIt, 0);
15774 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15777 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15787 EVT VT =
N->getValueType(0);
15791 if (Op0->
getOpcode() == ARMISD::VDUP) {
15793 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15794 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15795 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15796 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15797 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15800 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15801 X =
X->getOperand(0);
15802 if (
X.getValueType() == VT)
15810 return Op0.
getOperand(
N->getConstantOperandVal(1));
15820 unsigned Offset =
N->getConstantOperandVal(1);
15822 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15832 unsigned Idx =
N->getConstantOperandVal(1);
15847 unsigned Lane =
N->getConstantOperandVal(1);
15875 EVT VT =
N->getValueType(0);
15878 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15880 Op.getOperand(0).getValueType().getScalarType())
15881 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15890 SDValue SubVec =
N->getOperand(1);
15891 uint64_t IdxVal =
N->getConstantOperandVal(2);
15902 if (IdxVal == 0 && Vec.
isUndef())
15908 (IdxVal != 0 && IdxVal != NumSubElts))
15939 ARMISD::VMOVN,
DL, VT,
15945 ARMISD::VMOVN,
DL, VT,
15981 EVT VT =
N->getValueType(0);
15992 unsigned HalfElts = NumElts/2;
15994 for (
unsigned n = 0; n < NumElts; ++n) {
15997 if (MaskElt < (
int)HalfElts)
15999 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
16000 NewElt = HalfElts + MaskElt - NumElts;
16043 bool SimpleConstIncOnly,
16051 bool isLoadOp =
true;
16052 bool isLaneOp =
false;
16055 bool hasAlignment =
true;
16056 unsigned NewOpc = 0;
16057 unsigned NumVecs = 0;
16058 if (
Target.isIntrinsic) {
16059 unsigned IntNo =
N->getConstantOperandVal(1);
16063 case Intrinsic::arm_neon_vld1:
16067 case Intrinsic::arm_neon_vld2:
16071 case Intrinsic::arm_neon_vld3:
16075 case Intrinsic::arm_neon_vld4:
16079 case Intrinsic::arm_neon_vld1x2:
16082 hasAlignment =
false;
16084 case Intrinsic::arm_neon_vld1x3:
16087 hasAlignment =
false;
16089 case Intrinsic::arm_neon_vld1x4:
16092 hasAlignment =
false;
16094 case Intrinsic::arm_neon_vld2dup:
16098 case Intrinsic::arm_neon_vld3dup:
16102 case Intrinsic::arm_neon_vld4dup:
16106 case Intrinsic::arm_neon_vld2lane:
16111 case Intrinsic::arm_neon_vld3lane:
16116 case Intrinsic::arm_neon_vld4lane:
16121 case Intrinsic::arm_neon_vst1:
16126 case Intrinsic::arm_neon_vst2:
16127 NewOpc = ARMISD::VST2_UPD;
16131 case Intrinsic::arm_neon_vst3:
16136 case Intrinsic::arm_neon_vst4:
16137 NewOpc = ARMISD::VST4_UPD;
16141 case Intrinsic::arm_neon_vst2lane:
16147 case Intrinsic::arm_neon_vst3lane:
16153 case Intrinsic::arm_neon_vst4lane:
16159 case Intrinsic::arm_neon_vst1x2:
16163 hasAlignment =
false;
16165 case Intrinsic::arm_neon_vst1x3:
16169 hasAlignment =
false;
16171 case Intrinsic::arm_neon_vst1x4:
16175 hasAlignment =
false;
16180 switch (
N->getOpcode()) {
16216 VecTy =
N->getValueType(0);
16217 }
else if (
Target.isIntrinsic) {
16218 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16221 "Node has to be a load, a store, or an intrinsic!");
16222 VecTy =
N->getOperand(1).getValueType();
16230 if (isLaneOp || isVLDDUPOp)
16233 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16239 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16248 EVT AlignedVecTy = VecTy;
16268 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16269 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16280 Alignment =
Align(1);
16286 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16288 for (n = 0; n < NumResultVecs; ++n)
16289 Tys[n] = AlignedVecTy;
16290 Tys[n++] = MVT::i32;
16291 Tys[n] = MVT::Other;
16296 Ops.push_back(
N->getOperand(0));
16297 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16302 Ops.push_back(StN->getValue());
16306 unsigned LastOperand =
16307 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16308 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16309 Ops.push_back(
N->getOperand(i));
16313 Ops.push_back(DAG.
getConstant(Alignment.value(), dl, MVT::i32));
16317 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16328 for (
unsigned i = 0; i < NumResultVecs; ++i)
16333 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16334 SDValue &LdVal = NewResults[0];
16370 switch (
N->getOpcode()) {
16374 *Ptr =
N->getOperand(0);
16375 *CInc =
N->getOperand(1);
16382 *Ptr =
N->getOperand(1);
16383 *CInc =
N->getOperand(2);
16410 SDValue Addr =
N->getOperand(AddrOpIdx);
16421 unsigned ConstInc =
16426 if (BaseUpdates.
size() >= MaxBaseUpdates)
16447 unsigned UserOffset =
16450 if (!UserOffset || UserOffset <=
Offset)
16453 unsigned NewConstInc = UserOffset -
Offset;
16456 if (BaseUpdates.
size() >= MaxBaseUpdates)
16464 unsigned NumValidUpd = BaseUpdates.
size();
16465 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16476 return LHS.ConstInc <
RHS.ConstInc;
16505 unsigned IntNo =
N->getConstantOperandVal(1);
16506 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16508 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16531 bool isLoadOp =
true;
16532 unsigned NewOpc = 0;
16533 unsigned NumVecs = 0;
16537 case Intrinsic::arm_mve_vld2q:
16541 case Intrinsic::arm_mve_vld4q:
16545 case Intrinsic::arm_mve_vst2q:
16546 NewOpc = ARMISD::VST2_UPD;
16550 case Intrinsic::arm_mve_vst4q:
16551 NewOpc = ARMISD::VST4_UPD;
16560 VecTy =
N->getValueType(0);
16562 VecTy =
N->getOperand(3).getValueType();
16576 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16578 for (n = 0; n < NumResultVecs; ++n)
16580 Tys[n++] = MVT::i32;
16581 Tys[n] = MVT::Other;
16586 Ops.push_back(
N->getOperand(0));
16587 Ops.push_back(
N->getOperand(2));
16588 Ops.push_back(Inc);
16590 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16591 Ops.push_back(
N->getOperand(i));
16598 for (
unsigned i = 0; i < NumResultVecs; ++i)
16617 EVT VT =
N->getValueType(0);
16623 SDNode *VLD =
N->getOperand(0).getNode();
16626 unsigned NumVecs = 0;
16627 unsigned NewOpc = 0;
16629 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16632 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16635 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16647 if (
Use.getResNo() == NumVecs)
16650 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16651 VLDLaneNo !=
User->getConstantOperandVal(1))
16658 for (n = 0; n < NumVecs; ++n)
16660 Tys[n] = MVT::Other;
16670 unsigned ResNo =
Use.getResNo();
16672 if (ResNo == NumVecs)
16679 std::vector<SDValue> VLDDupResults;
16680 for (
unsigned n = 0; n < NumVecs; ++n)
16694 EVT VT =
N->getValueType(0);
16697 if (Subtarget->hasMVEIntegerOps()) {
16701 ExtractVT = MVT::i32;
16703 N->getOperand(0),
N->getOperand(1));
16715 Op =
Op.getOperand(0);
16716 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16720 unsigned EltSize =
Op.getScalarValueSizeInBits();
16722 unsigned Imm =
Op.getConstantOperandVal(0);
16738 if (Subtarget->hasMVEIntegerOps()) {
16741 if (
Op.getValueType() == MVT::f32)
16742 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16744 else if (
Op.getValueType() == MVT::f16)
16745 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16746 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16749 if (!Subtarget->hasNEON())
16756 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16757 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16758 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16763 LD->getMemoryVT(), LD->getMemOperand());
16774 EVT VT =
N->getValueType(0);
16793 SDValue StVal = St->getValue();
16795 if (!St->isTruncatingStore() || !VT.
isVector())
16798 EVT StVT = St->getMemoryVT();
16800 assert(StVT != VT &&
"Cannot truncate to the same type");
16810 if (0 != (NumElems * FromEltSz) % ToEltSz)
16813 unsigned SizeRatio = FromEltSz / ToEltSz;
16818 NumElems * SizeRatio);
16824 for (
unsigned i = 0; i < NumElems; ++i)
16838 MVT StoreType = MVT::i8;
16840 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16856 SDValue BasePtr = St->getBasePtr();
16860 for (
unsigned I = 0;
I <
E;
I++) {
16864 DAG.
getStore(St->getChain(),
DL, SubVec, BasePtr, St->getPointerInfo(),
16865 St->getAlign(), St->getMemOperand()->getFlags());
16878 if (!St->isSimple() || St->isTruncatingStore() || !St->isUnindexed())
16880 SDValue Trunc = St->getValue();
16891 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16894 unsigned NumElements = 4;
16911 unsigned Off0 = Rev ? NumElts : 0;
16912 unsigned Off1 = Rev ? 0 : NumElts;
16914 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16915 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16917 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16925 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16932 SDValue BasePtr = St->getBasePtr();
16933 Align Alignment = St->getBaseAlign();
16945 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16956 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16959 Ch,
DL, Extract, NewPtr, St->getPointerInfo().getWithOffset(NewOffset),
16960 NewToVT, Alignment, MMOFlags, AAInfo);
16971 if (!St->isSimple() || St->isTruncatingStore() || !St->isUnindexed())
16973 SDValue Trunc = St->getValue();
16983 SDValue BasePtr = St->getBasePtr();
16984 Align Alignment = St->getBaseAlign();
16993 unsigned NewOffset =
17000 Ch,
DL, Extract, NewPtr, St->getPointerInfo().getWithOffset(NewOffset),
17001 NewToVT, Alignment, MMOFlags, AAInfo);
17012 if (!St->isSimple() || St->isTruncatingStore() || !St->isUnindexed())
17014 SDValue Extract = St->getValue();
17023 {Extract.getOperand(0), Extract.getOperand(1)});
17031 SDValue BasePtr = St->getBasePtr();
17032 Align Alignment = St->getBaseAlign();
17037 St->getPointerInfo(), NewToVT, Alignment,
17056 SDValue StoredValue = ST->getValue();
17062 if (NumParts < 2 || NumParts > 4)
17065 if (NumParts == 3 && Subtarget->hasMVEIntegerOps())
17072 if (Subtarget->hasMVEIntegerOps() && !SubVecTy.
is128BitVector())
17075 if (EltBits != 8 && EltBits != 16 && EltBits != 32)
17080 unsigned ResNo =
Use.getResNo();
17082 if (Stores[ResNo] || !
Store)
17084 Stores[ResNo] =
Store;
17091 if (Subtarget->hasMVEIntegerOps() && BaseStore->
getAlign() < EltBits / 8)
17099 static constexpr Intrinsic::ID NEONStores[] = {Intrinsic::arm_neon_vst2,
17100 Intrinsic::arm_neon_vst3,
17101 Intrinsic::arm_neon_vst4};
17107 if (Subtarget->hasNEON())
17108 IID = NEONStores[NumParts - 2];
17110 IID = NumParts == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
17125 if (Subtarget->hasNEON()) {
17130 for (
unsigned Stage = 0; Stage < NumParts; Stage++) {
17134 Ops.front() = NewStore;
17150 unsigned NumParts =
N->getNumOperands();
17154 SDNode *InterleaveOp =
N->getOperand(0).getNode();
17156 InterleaveOp->getNumOperands() != NumParts)
17159 for (
unsigned I = 0;
I < NumParts;
I++)
17160 if (
N->getOperand(
I) !=
SDValue(InterleaveOp,
I))
17163 Ops.append(InterleaveOp->op_begin(), InterleaveOp->op_end());
17170 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
17182 SDValue WideValue = ST->getValue();
17185 ValueInterleaveOps))
17191 unsigned NumParts = ValueInterleaveOps.
size();
17192 if (NumParts != 2 && NumParts != 3 && NumParts != 4)
17195 if (NumParts == 3 && Subtarget->hasMVEIntegerOps())
17198 EVT SubVecTy = ValueInterleaveOps[0].getValueType();
17202 if (Subtarget->hasMVEIntegerOps() && !SubVecTy.
is128BitVector())
17205 if (EltBits != 8 && EltBits != 16 && EltBits != 32)
17207 if (Subtarget->hasMVEIntegerOps() && ST->getAlign() < EltBits / 8)
17209 static constexpr Intrinsic::ID NEONStores[] = {Intrinsic::arm_neon_vst2,
17210 Intrinsic::arm_neon_vst3,
17211 Intrinsic::arm_neon_vst4};
17214 Ops.push_back(ST->getChain());
17216 if (Subtarget->hasNEON())
17217 IID = NEONStores[NumParts - 2];
17219 IID = NumParts == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
17223 Ops.push_back(ST->getBasePtr());
17224 Ops.append(ValueInterleaveOps);
17227 if (Subtarget->hasNEON())
17230 ST->getMemoryVT(), ST->getMemOperand());
17233 for (
unsigned Stage = 0; Stage < NumParts; Stage++) {
17237 ST->getMemoryVT(), ST->getMemOperand());
17238 Ops.front() = NewStore;
17249 if (St->isVolatile())
17251 SDValue StVal = St->getValue();
17257 if (Subtarget->hasNEON())
17261 if (Subtarget->hasMVEFloatOps())
17265 if (Subtarget->hasMVEIntegerOps()) {
17282 SDValue BasePtr = St->getBasePtr();
17285 BasePtr, St->getPointerInfo(), St->getBaseAlign(),
17286 St->getMemOperand()->getFlags());
17292 St->getPointerInfo().getWithOffset(4),
17293 St->getBaseAlign(), St->getMemOperand()->
getFlags());
17315 return DAG.
getStore(St->getChain(), dl, V, St->getBasePtr(),
17316 St->getPointerInfo(), St->getAlign(),
17317 St->getMemOperand()->getFlags(), St->getAAInfo());
17339 if (!Subtarget->hasNEON())
17343 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
17351 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
17353 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
17354 uint32_t IntBits = IntTy.getSizeInBits();
17355 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17356 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17367 if (
C == -1 ||
C == 0 ||
C > 32)
17372 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
17373 Intrinsic::arm_neon_vcvtfp2fxu;
17376 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
17379 if (IntBits < FloatBits)
17387 if (!Subtarget->hasMVEFloatOps())
17395 EVT VT =
N->getValueType(0);
17400 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
17402 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
17404 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
17405 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
17407 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17420 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17431 EVT VT =
N->getValueType(0);
17434 if (!
N->getFlags().hasAllowReassociation())
17441 unsigned Opc =
A.getConstantOperandVal(0);
17442 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17447 A.getOperand(3),
A.getOperand(4));
17479 if (!Subtarget->hasNEON())
17483 unsigned OpOpcode =
Op.getNode()->getOpcode();
17484 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17488 SDValue ConstVec =
N->getOperand(1);
17492 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17494 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17495 uint32_t IntBits = IntTy.getSizeInBits();
17496 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17497 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17517 int32_t
C = IntVal.exactLogBase2();
17518 if (
C == -1 ||
C == 0 ||
C > 32)
17524 if (IntBits < FloatBits)
17526 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17528 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17529 : Intrinsic::arm_neon_vcvtfxu2fp;
17537 if (!ST->hasMVEIntegerOps())
17541 EVT ResVT =
N->getValueType(0);
17569 EVT AVT =
A.getValueType();
17575 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17576 EVT AVT =
A.getValueType();
17586 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17587 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17590 if (ExtTypeMatches(
A, ExtTypes))
17591 return ExtendIfNeeded(
A, ExtendCode);
17594 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17604 if (ExtTypeMatches(
A, ExtTypes))
17605 return ExtendIfNeeded(
A, ExtendCode);
17608 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17618 if (ResVT != RetTy)
17621 if (
Mul->getOpcode() == ExtendCode &&
17622 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17624 Mul =
Mul->getOperand(0);
17633 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17634 A = ExtendIfNeeded(
A, ExtendCode);
17635 B = ExtendIfNeeded(
B, ExtendCode);
17640 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17653 if (
Mul->getOpcode() == ExtendCode &&
17654 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17656 Mul =
Mul->getOperand(0);
17665 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17666 A = ExtendIfNeeded(
A, ExtendCode);
17667 B = ExtendIfNeeded(
B, ExtendCode);
17678 EVT VT =
Ops[0].getValueType();
17679 if (VT == MVT::v16i8) {
17680 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17681 "Unexpected illegal long reduction opcode");
17682 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17694 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17707 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17709 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17710 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17712 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17713 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17715 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17718 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17721 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17725 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17728 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17731 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17734 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17737 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17740 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17743 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17745 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17747 return Create64bitNode(ARMISD::VADDLVs, {
A});
17749 return Create64bitNode(ARMISD::VADDLVu, {
A});
17752 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17755 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17758 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17760 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17762 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17764 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17767 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17770 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17777 Op =
Op->getOperand(1);
17779 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17781 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17798 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17800 if (!Shuf || !Shuf->getOperand(1).isUndef())
17805 APInt SetElts(Mask.size(), 0);
17806 for (
int E : Mask) {
17814 if (
N->getNumOperands() != VecOp + 1) {
17816 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17822 if (
Op.getValueType().isVector())
17823 Ops.push_back(
Op.getOperand(0));
17834 unsigned IsTop =
N->getConstantOperandVal(2);
17841 if (Op0->
isUndef() && !IsTop)
17846 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17847 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17855 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17857 APInt Op0DemandedElts =
17858 IsTop ? Op1DemandedElts
17873 unsigned IsTop =
N->getConstantOperandVal(2);
17875 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17876 APInt Op0DemandedElts =
17888 EVT VT =
N->getValueType(0);
17895 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17896 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17900 LHS.getOperand(0),
RHS.getOperand(0));
17915 int ShiftAmt =
C->getSExtValue();
17916 if (ShiftAmt == 0) {
17922 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17923 unsigned NewOpcode =
17924 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17939 unsigned IntNo =
N->getConstantOperandVal(0);
17950 case Intrinsic::arm_neon_vshifts:
17951 case Intrinsic::arm_neon_vshiftu:
17952 case Intrinsic::arm_neon_vrshifts:
17953 case Intrinsic::arm_neon_vrshiftu:
17954 case Intrinsic::arm_neon_vrshiftn:
17955 case Intrinsic::arm_neon_vqshifts:
17956 case Intrinsic::arm_neon_vqshiftu:
17957 case Intrinsic::arm_neon_vqshiftsu:
17958 case Intrinsic::arm_neon_vqshiftns:
17959 case Intrinsic::arm_neon_vqshiftnu:
17960 case Intrinsic::arm_neon_vqshiftnsu:
17961 case Intrinsic::arm_neon_vqrshiftns:
17962 case Intrinsic::arm_neon_vqrshiftnu:
17963 case Intrinsic::arm_neon_vqrshiftnsu: {
17964 EVT VT =
N->getOperand(1).getValueType();
17966 unsigned VShiftOpc = 0;
17969 case Intrinsic::arm_neon_vshifts:
17970 case Intrinsic::arm_neon_vshiftu:
17972 VShiftOpc = ARMISD::VSHLIMM;
17975 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17976 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17977 : ARMISD::VSHRuIMM);
17982 case Intrinsic::arm_neon_vrshifts:
17983 case Intrinsic::arm_neon_vrshiftu:
17988 case Intrinsic::arm_neon_vqshifts:
17989 case Intrinsic::arm_neon_vqshiftu:
17994 case Intrinsic::arm_neon_vqshiftsu:
17999 case Intrinsic::arm_neon_vrshiftn:
18000 case Intrinsic::arm_neon_vqshiftns:
18001 case Intrinsic::arm_neon_vqshiftnu:
18002 case Intrinsic::arm_neon_vqshiftnsu:
18003 case Intrinsic::arm_neon_vqrshiftns:
18004 case Intrinsic::arm_neon_vqrshiftnu:
18005 case Intrinsic::arm_neon_vqrshiftnsu:
18017 case Intrinsic::arm_neon_vshifts:
18018 case Intrinsic::arm_neon_vshiftu:
18021 case Intrinsic::arm_neon_vrshifts:
18022 VShiftOpc = ARMISD::VRSHRsIMM;
18024 case Intrinsic::arm_neon_vrshiftu:
18025 VShiftOpc = ARMISD::VRSHRuIMM;
18027 case Intrinsic::arm_neon_vrshiftn:
18028 VShiftOpc = ARMISD::VRSHRNIMM;
18030 case Intrinsic::arm_neon_vqshifts:
18031 VShiftOpc = ARMISD::VQSHLsIMM;
18033 case Intrinsic::arm_neon_vqshiftu:
18034 VShiftOpc = ARMISD::VQSHLuIMM;
18036 case Intrinsic::arm_neon_vqshiftsu:
18037 VShiftOpc = ARMISD::VQSHLsuIMM;
18039 case Intrinsic::arm_neon_vqshiftns:
18040 VShiftOpc = ARMISD::VQSHRNsIMM;
18042 case Intrinsic::arm_neon_vqshiftnu:
18043 VShiftOpc = ARMISD::VQSHRNuIMM;
18045 case Intrinsic::arm_neon_vqshiftnsu:
18046 VShiftOpc = ARMISD::VQSHRNsuIMM;
18048 case Intrinsic::arm_neon_vqrshiftns:
18049 VShiftOpc = ARMISD::VQRSHRNsIMM;
18051 case Intrinsic::arm_neon_vqrshiftnu:
18052 VShiftOpc = ARMISD::VQRSHRNuIMM;
18054 case Intrinsic::arm_neon_vqrshiftnsu:
18055 VShiftOpc = ARMISD::VQRSHRNsuIMM;
18060 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
18061 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
18064 case Intrinsic::arm_neon_vshiftins: {
18065 EVT VT =
N->getOperand(1).getValueType();
18067 unsigned VShiftOpc = 0;
18070 VShiftOpc = ARMISD::VSLIIMM;
18071 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
18072 VShiftOpc = ARMISD::VSRIIMM;
18078 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
18079 N->getOperand(1),
N->getOperand(2),
18083 case Intrinsic::arm_neon_vqrshifts:
18084 case Intrinsic::arm_neon_vqrshiftu:
18088 case Intrinsic::arm_neon_vbsl: {
18090 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
18091 N->getOperand(2),
N->getOperand(3));
18093 case Intrinsic::arm_mve_vqdmlah:
18094 case Intrinsic::arm_mve_vqdmlash:
18095 case Intrinsic::arm_mve_vqrdmlah:
18096 case Intrinsic::arm_mve_vqrdmlash:
18097 case Intrinsic::arm_mve_vmla_n_predicated:
18098 case Intrinsic::arm_mve_vmlas_n_predicated:
18099 case Intrinsic::arm_mve_vqdmlah_predicated:
18100 case Intrinsic::arm_mve_vqdmlash_predicated:
18101 case Intrinsic::arm_mve_vqrdmlah_predicated:
18102 case Intrinsic::arm_mve_vqrdmlash_predicated: {
18107 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
18114 case Intrinsic::arm_mve_minv:
18115 case Intrinsic::arm_mve_maxv:
18116 case Intrinsic::arm_mve_minav:
18117 case Intrinsic::arm_mve_maxav:
18118 case Intrinsic::arm_mve_minv_predicated:
18119 case Intrinsic::arm_mve_maxv_predicated:
18120 case Intrinsic::arm_mve_minav_predicated:
18121 case Intrinsic::arm_mve_maxav_predicated: {
18124 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
18131 case Intrinsic::arm_mve_addv: {
18134 bool Unsigned =
N->getConstantOperandVal(2);
18135 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
18139 case Intrinsic::arm_mve_addlv:
18140 case Intrinsic::arm_mve_addlv_predicated: {
18143 bool Unsigned =
N->getConstantOperandVal(2);
18144 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
18145 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
18146 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
18149 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
18151 Ops.push_back(
N->getOperand(i));
18164 EVT VT =
Y.getValueType();
18167 if (Subtarget->hasMVEIntegerOps())
18169 if (Subtarget->hasNEON())
18183 EVT VT =
N->getValueType(0);
18185 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
18186 N->getOperand(0)->getOpcode() ==
ISD::AND &&
18187 N->getOperand(0)->hasOneUse()) {
18204 if (AndMask == 255 || AndMask == 65535)
18208 if (MaskedBits > ShiftAmt) {
18223 if (ST->hasMVEIntegerOps())
18228 switch (
N->getOpcode()) {
18234 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
18241 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
18242 unsigned VShiftOpc =
18243 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
18245 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
18261 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
18264 EVT FromVT = LD->getValueType(0);
18265 EVT ToVT =
N->getValueType(0);
18272 unsigned NumElements = 0;
18273 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
18275 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
18277 if (NumElements == 0 ||
18287 SDValue BasePtr = LD->getBasePtr();
18288 Align Alignment = LD->getBaseAlign();
18309 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18310 Alignment, MMOFlags, AAInfo);
18316 if (FromEltVT == MVT::f16) {
18319 for (
unsigned i = 0; i < Loads.
size(); i++) {
18321 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
18340 EVT VT =
N->getValueType(0);
18347 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
18354 if (VT == MVT::i32 &&
18355 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
18360 switch (
N->getOpcode()) {
18363 Opc = ARMISD::VGETLANEs;
18367 Opc = ARMISD::VGETLANEu;
18374 if (ST->hasMVEIntegerOps())
18392 Ops.push_back(Ext);
18402 if (ST->hasMVEFloatOps())
18413 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
18417 EVT VT =
Op.getValueType();
18420 if (VT != MVT::i32 ||
18436 APInt MaxC = Max.getConstantOperandAPInt(1);
18437 if (MaxC.
sgt(MinC))
18444 if ((MinC + 1).isPowerOf2()) {
18466 APInt Width = MinC - MaxC + 1;
18469 unsigned SatBit = Width.
logBase2() - 1;
18487 EVT VT =
N->getValueType(0);
18490 if (VT == MVT::i32)
18493 if (!ST->hasMVEIntegerOps())
18499 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18502 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18510 if (VT == MVT::v4i32)
18511 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18513 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18520 MaxC != ~SaturateC)
18525 if (IsSignedSaturate(
N, N0.
getNode())) {
18528 if (VT == MVT::v4i32) {
18529 HalfVT = MVT::v8i16;
18530 ExtVT = MVT::v4i16;
18532 HalfVT = MVT::v16i8;
18547 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18553 if (VT == MVT::v4i32)
18554 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18556 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18565 if (IsUnsignedSaturate(
N)) {
18569 if (VT == MVT::v4i32) {
18570 HalfVT = MVT::v8i16;
18571 ExtConst = 0x0000FFFF;
18573 HalfVT = MVT::v16i8;
18595 const APInt *CV = &
C->getAPIntValue();
18652 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18659 if ((OrCI &
Known.Zero) != OrCI)
18665 EVT VT =
X.getValueType();
18666 unsigned BitInX = AndC->
logBase2();
18674 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18675 BitInY < NumActiveBits; ++BitInY) {
18676 if (OrCI[BitInY] == 0)
18679 Mask.setBit(BitInY);
18680 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18696 switch (
N->getOpcode()) {
18711 if (Const->isZero())
18713 else if (Const->isOne())
18721 unsigned IntOp =
N.getConstantOperandVal(1);
18722 if (IntOp != Intrinsic::test_start_loop_iterations &&
18723 IntOp != Intrinsic::loop_decrement_reg)
18749 bool Negate =
false;
18755 Cond =
N->getOperand(1);
18756 Dest =
N->getOperand(2);
18760 Cond =
N->getOperand(2);
18761 Dest =
N->getOperand(4);
18763 if (!Const->isOne() && !Const->isZero())
18765 Imm = Const->getZExtValue();
18794 "unsupported condition");
18799 unsigned IntOp =
Int->getConstantOperandVal(1);
18800 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18801 "expected single br user");
18802 SDNode *Br = *
N->user_begin();
18812 if (IntOp == Intrinsic::test_start_loop_iterations) {
18814 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18816 if (IsTrueIfZero(
CC,
Imm)) {
18818 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18822 UpdateUncondBr(Br, Dest, DAG);
18824 SDValue Ops[] = {Chain, Setup, OtherTarget};
18825 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18837 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18845 if (
Target == OtherTarget)
18846 UpdateUncondBr(Br, Dest, DAG);
18852 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18861 if (Cmp.getOpcode() != ARMISD::CMPZ)
18866 SDValue LHS = Cmp.getOperand(0);
18867 SDValue RHS = Cmp.getOperand(1);
18876 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18877 LHS->getOperand(0)->hasOneUse() &&
18881 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18893 EVT VT =
N->getValueType(0);
18894 SDValue FalseVal =
N->getOperand(0);
18895 SDValue TrueVal =
N->getOperand(1);
18903 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18910 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18913 if (Cmp.getOpcode() != ARMISD::CMPZ)
18917 SDValue LHS = Cmp.getOperand(0);
18918 SDValue RHS = Cmp.getOperand(1);
18922 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18946 if (
CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18947 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18951 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18956 if (
CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18959 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18960 LHS->getOperand(2), LHS->getOperand(3));
18970 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18974 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18976 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18985 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18990 if (VT == MVT::i32 && Subtarget->isThumb2() &&
isNullConstant(RHS) &&
19024 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
19036 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
19056 const APInt *TrueConst;
19057 if (Subtarget->isThumb1Only() &&
CC ==
ARMCC::NE &&
19058 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
19059 FalseVal.getOperand(1) == RHS) ||
19063 unsigned ShiftAmount = TrueConst->
logBase2();
19078 if (
Known.Zero == 0xfffffffe)
19081 else if (
Known.Zero == 0xffffff00)
19084 else if (
Known.Zero == 0xffff0000)
19097 EVT DstVT =
N->getValueType(0);
19100 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
19101 EVT SrcVT = Src.getValueType();
19103 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
19108 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
19109 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
19110 Src.getValueType().getScalarSizeInBits())
19111 Src = Src.getOperand(0);
19115 EVT SrcVT = Src.getValueType();
19116 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
19117 Src.getOpcode() == ARMISD::VMVNIMM ||
19118 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
19121 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
19135 EVT VT =
N->getValueType(0);
19143 if (
N->getNumOperands() == 2 &&
19147 N->getOperand(0).getOperand(1),
19148 N->getOperand(1).getOperand(0),
19149 N->getOperand(1).getOperand(1));
19152 if (
N->getNumOperands() == 2 &&
19158 if (S0->getOperand(0) ==
S1->getOperand(0) &&
19159 S0->getOperand(1) ==
S1->getOperand(1)) {
19162 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
19166 ARMISD::VMOVN,
DL, VT,
19167 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
19168 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
19172 ARMISD::VMOVN,
DL, VT,
19173 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
19174 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
19182 return Op.getOpcode() == ISD::BUILD_VECTOR ||
19183 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
19184 (Op.getOpcode() == ISD::BITCAST &&
19185 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
19188 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
19190 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
19208 int NumIns =
N->getNumOperands();
19209 assert((NumIns == 2 || NumIns == 4) &&
19210 "Expected 2 or 4 inputs to an MVETrunc");
19212 if (
N->getNumOperands() == 4)
19216 for (
int I = 0;
I < NumIns;
I++) {
19218 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
19223 Ptr, MPI, StoreVT,
Align(4));
19238 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
19241 EVT FromVT = LD->getMemoryVT();
19242 EVT ToVT =
N->getValueType(0);
19249 unsigned NumElements = 0;
19250 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
19252 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
19254 assert(NumElements != 0);
19260 LD->getExtensionType() != NewExtType)
19267 SDValue BasePtr = LD->getBasePtr();
19268 Align Alignment = LD->getBaseAlign();
19287 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
19288 Alignment, MMOFlags, AAInfo);
19304 EVT VT =
N->getValueType(0);
19306 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
19307 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
19309 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19311 auto Extend = [&](
SDValue V) {
19320 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
19321 SDValue Ext = Extend(
N->getOperand(0));
19329 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
19330 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
19334 auto CheckInregMask = [&](
int Start,
int Offset) {
19336 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
19342 if (CheckInregMask(0, 0))
19344 else if (CheckInregMask(0, 1))
19345 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19346 else if (CheckInregMask(0, Mask.size()))
19348 else if (CheckInregMask(0, Mask.size() + 1))
19349 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19354 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
19358 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
19360 if (V0.getNode() !=
N ||
V1.getNode() !=
N)
19365 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
19376 int NumOuts =
N->getNumValues();
19377 assert((NumOuts == 2 || NumOuts == 4) &&
19378 "Expected 2 or 4 outputs to an MVEEXT");
19379 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19381 if (
N->getNumOperands() == 4)
19387 StackPtr, MPI,
Align(4));
19390 for (
int I = 0;
I < NumOuts;
I++) {
19392 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
19393 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
19398 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
19407 switch (
N->getOpcode()) {
19467 case ARMISD::BRCOND:
19471 case ARMISD::CSINC:
19472 case ARMISD::CSINV:
19473 case ARMISD::CSNEG:
19488 case ARMISD::PREDICATE_CAST:
19490 case ARMISD::VECTOR_REG_CAST:
19501 case ARMISD::VADDVs:
19502 case ARMISD::VADDVu:
19503 case ARMISD::VADDLVs:
19504 case ARMISD::VADDLVu:
19505 case ARMISD::VADDLVAs:
19506 case ARMISD::VADDLVAu:
19507 case ARMISD::VMLAVs:
19508 case ARMISD::VMLAVu:
19509 case ARMISD::VMLALVs:
19510 case ARMISD::VMLALVu:
19511 case ARMISD::VMLALVAs:
19512 case ARMISD::VMLALVAu:
19514 case ARMISD::VMOVN:
19516 case ARMISD::VQMOVNs:
19517 case ARMISD::VQMOVNu:
19519 case ARMISD::VQDMULH:
19525 case ARMISD::SMULWB: {
19526 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19532 case ARMISD::SMULWT: {
19533 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19539 case ARMISD::SMLALBB:
19540 case ARMISD::QADD16b:
19541 case ARMISD::QSUB16b:
19542 case ARMISD::UQADD16b:
19543 case ARMISD::UQSUB16b: {
19544 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19551 case ARMISD::SMLALBT: {
19552 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19554 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19561 case ARMISD::SMLALTB: {
19562 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19564 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19571 case ARMISD::SMLALTT: {
19572 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19579 case ARMISD::QADD8b:
19580 case ARMISD::QSUB8b:
19581 case ARMISD::UQADD8b:
19582 case ARMISD::UQSUB8b: {
19583 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19591 if (
N->getOperand(1) ==
N->getOperand(2))
19592 return N->getOperand(1);
19596 switch (
N->getConstantOperandVal(1)) {
19597 case Intrinsic::arm_neon_vld1:
19598 case Intrinsic::arm_neon_vld1x2:
19599 case Intrinsic::arm_neon_vld1x3:
19600 case Intrinsic::arm_neon_vld1x4:
19601 case Intrinsic::arm_neon_vld2:
19602 case Intrinsic::arm_neon_vld3:
19603 case Intrinsic::arm_neon_vld4:
19604 case Intrinsic::arm_neon_vld2lane:
19605 case Intrinsic::arm_neon_vld3lane:
19606 case Intrinsic::arm_neon_vld4lane:
19607 case Intrinsic::arm_neon_vld2dup:
19608 case Intrinsic::arm_neon_vld3dup:
19609 case Intrinsic::arm_neon_vld4dup:
19610 case Intrinsic::arm_neon_vst1:
19611 case Intrinsic::arm_neon_vst1x2:
19612 case Intrinsic::arm_neon_vst1x3:
19613 case Intrinsic::arm_neon_vst1x4:
19614 case Intrinsic::arm_neon_vst2:
19615 case Intrinsic::arm_neon_vst3:
19616 case Intrinsic::arm_neon_vst4:
19617 case Intrinsic::arm_neon_vst2lane:
19618 case Intrinsic::arm_neon_vst3lane:
19619 case Intrinsic::arm_neon_vst4lane:
19621 case Intrinsic::arm_mve_vld2q:
19622 case Intrinsic::arm_mve_vld4q:
19623 case Intrinsic::arm_mve_vst2q:
19624 case Intrinsic::arm_mve_vst4q:
19641 unsigned *
Fast)
const {
19647 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19650 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19652 if (AllowsUnaligned) {
19654 *
Fast = Subtarget->hasV7Ops();
19659 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19663 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19670 if (!Subtarget->hasMVEIntegerOps())
19674 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19675 Ty == MVT::v2i1)) {
19683 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19699 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19700 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19701 Ty == MVT::v2f64) {
19714 if ((
Op.isMemcpyOrMemmove() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19715 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19717 if (
Op.size() >= 16 &&
19723 }
else if (
Op.size() >= 8 &&
19740 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19742 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19744 return (SrcBits == 64 && DestBits == 32);
19753 return (SrcBits == 64 && DestBits == 32);
19789 return Subtarget->hasFullFP16();
19796 if (!Subtarget->hasMVEIntegerOps())
19815 if (Ld->isExpandingLoad())
19819 if (Subtarget->hasMVEIntegerOps())
19832 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19864bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19866 if (Subtarget->useSoftFloat())
19875 return Subtarget->hasMVEFloatOps();
19893 unsigned Scale = 1;
19910 if ((V & (Scale - 1)) != 0)
19919 if (VT.
isVector() && Subtarget->hasNEON())
19922 !Subtarget->hasMVEFloatOps())
19925 bool IsNeg =
false;
19931 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19934 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19950 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19956 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19986 default:
return false;
20005 int Scale = AM.
Scale;
20010 default:
return false;
20018 Scale = Scale & ~1;
20019 return Scale == 2 || Scale == 4 || Scale == 8;
20036 if (Scale & 1)
return false;
20043 const int Scale = AM.
Scale;
20053 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
20069 switch (AM.
Scale) {
20080 if (Subtarget->isThumb1Only())
20083 if (Subtarget->isThumb2())
20086 int Scale = AM.
Scale;
20088 default:
return false;
20092 if (Scale < 0) Scale = -Scale;
20100 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
20113 if (Scale & 1)
return false;
20126 if (!Subtarget->isThumb())
20129 if (Subtarget->isThumb2())
20133 return Imm >= 0 &&
Imm <= 255;
20143 if (!Subtarget->isThumb())
20145 if (Subtarget->isThumb2())
20148 return AbsImm <= 255;
20183 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
20187 int RHSC = (int)
RHS->getZExtValue();
20188 if (RHSC < 0 && RHSC > -256) {
20198 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
20201 int RHSC = (int)
RHS->getZExtValue();
20202 if (RHSC < 0 && RHSC > -0x1000) {
20244 int RHSC = (int)
RHS->getZExtValue();
20245 if (RHSC < 0 && RHSC > -0x100) {
20250 }
else if (RHSC > 0 && RHSC < 0x100) {
20261 bool isSEXTLoad,
bool IsMasked,
bool isLE,
20272 bool CanChangeType = isLE && !IsMasked;
20275 int RHSC = (int)
RHS->getZExtValue();
20277 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
20278 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
20283 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
20294 if (VT == MVT::v4i16) {
20295 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
20297 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
20298 if (IsInRange(RHSC, 0x80, 1))
20300 }
else if (Alignment >= 4 &&
20301 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
20302 IsInRange(RHSC, 0x80, 4))
20304 else if (Alignment >= 2 &&
20305 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
20306 IsInRange(RHSC, 0x80, 2))
20308 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
20321 if (Subtarget->isThumb1Only())
20328 bool isSEXTLoad =
false;
20329 bool IsMasked =
false;
20331 Ptr = LD->getBasePtr();
20332 VT = LD->getMemoryVT();
20333 Alignment = LD->getAlign();
20334 AS = LD->getAddressSpace();
20337 Ptr = ST->getBasePtr();
20338 VT = ST->getMemoryVT();
20339 Alignment = ST->getAlign();
20340 AS = ST->getAddressSpace();
20342 Ptr = LD->getBasePtr();
20343 VT = LD->getMemoryVT();
20344 Alignment = LD->getAlign();
20345 AS = LD->getAddressSpace();
20349 Ptr = ST->getBasePtr();
20350 VT = ST->getMemoryVT();
20351 Alignment = ST->getAlign();
20352 AS = ST->getAddressSpace();
20367 bool isLegal =
false;
20369 isLegal = Subtarget->hasMVEIntegerOps() &&
20371 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
20372 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
20374 if (Subtarget->isThumb2())
20399 bool isSEXTLoad =
false, isNonExt;
20400 bool IsMasked =
false;
20402 VT = LD->getMemoryVT();
20403 Ptr = LD->getBasePtr();
20404 Alignment = LD->getAlign();
20408 VT = ST->getMemoryVT();
20409 Ptr = ST->getBasePtr();
20410 Alignment = ST->getAlign();
20411 isNonExt = !ST->isTruncatingStore();
20413 VT = LD->getMemoryVT();
20414 Ptr = LD->getBasePtr();
20415 Alignment = LD->getAlign();
20420 VT = ST->getMemoryVT();
20421 Ptr = ST->getBasePtr();
20422 Alignment = ST->getAlign();
20423 isNonExt = !ST->isTruncatingStore();
20428 if (Subtarget->isThumb1Only()) {
20431 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
20432 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
20435 if (!RHS || RHS->getZExtValue() != 4)
20437 if (Alignment <
Align(4))
20441 Base =
Op->getOperand(0);
20447 bool isLegal =
false;
20449 isLegal = Subtarget->hasMVEIntegerOps() &&
20454 if (Subtarget->isThumb2())
20468 !Subtarget->isThumb2())
20482 const APInt &DemandedElts,
20484 unsigned Depth)
const {
20487 switch (
Op.getOpcode()) {
20494 if (
Op.getResNo() == 0) {
20505 case ARMISD::CMOV: {
20508 if (
Known.isUnknown())
20520 case Intrinsic::arm_ldaex:
20521 case Intrinsic::arm_ldrex: {
20529 case ARMISD::BFI: {
20536 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20537 Known.Zero &= Mask;
20541 case ARMISD::VGETLANEs:
20542 case ARMISD::VGETLANEu: {
20543 const SDValue &SrcSV =
Op.getOperand(0);
20549 "VGETLANE index out of bounds");
20554 EVT VT =
Op.getValueType();
20560 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20568 case ARMISD::VMOVrh: {
20574 case ARMISD::CSINC:
20575 case ARMISD::CSINV:
20576 case ARMISD::CSNEG: {
20584 if (
Op.getOpcode() == ARMISD::CSINC)
20587 else if (
Op.getOpcode() == ARMISD::CSINV)
20589 else if (
Op.getOpcode() == ARMISD::CSNEG)
20596 case ARMISD::VORRIMM:
20597 case ARMISD::VBICIMM: {
20598 unsigned Encoded =
Op.getConstantOperandVal(1);
20599 unsigned DecEltBits = 0;
20602 unsigned EltBits =
Op.getScalarValueSizeInBits();
20603 if (EltBits != DecEltBits) {
20612 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20613 APInt Imm(DecEltBits, DecodedVal);
20624 if (!Subtarget->isThumb())
20641 if (
Imm == 0 ||
Imm == ~0U)
20644 unsigned Opc =
Op.getOpcode();
20646 EVT VT =
Op.getValueType();
20648 unsigned ShrunkImm =
Imm & Demanded;
20649 unsigned ExpandedImm =
Imm | ~Demanded;
20651 auto IsLegalImm = [ShrunkImm, ExpandedImm](
unsigned CandidateImm) ->
bool {
20652 return (ShrunkImm & CandidateImm) == ShrunkImm &&
20653 (~ExpandedImm & CandidateImm) == 0;
20655 auto UseImm = [
Imm,
Opc,
Op, VT, &TLO](
unsigned NewImm) ->
bool {
20667 if (ShrunkImm == 0) {
20668 ++NumOptimizedImms;
20669 return UseImm(ShrunkImm);
20675 if (ExpandedImm == ~0U) {
20676 ++NumOptimizedImms;
20677 return UseImm(ExpandedImm);
20685 if (IsLegalImm(0xFF)) {
20686 ++NumOptimizedImms;
20687 return UseImm(0xFF);
20690 if (IsLegalImm(0xFFFF)) {
20691 ++NumOptimizedImms;
20692 return UseImm(0xFFFF);
20706 ++NumOptimizedImms;
20707 return UseImm(ShrunkImm);
20715 if ((~ExpandedImm) < 256) {
20716 ++NumOptimizedImms;
20717 return UseImm(ExpandedImm);
20723 !Subtarget->hasV6Ops()) {
20724 ++NumOptimizedImms;
20725 return UseImm(ExpandedImm);
20744 EVT VT =
Op.getValueType();
20759 switch (
Op.getOpcode()) {
20770 unsigned Imm =
C->getZExtValue();
20777 unsigned Depth)
const {
20778 unsigned Opc =
Op.getOpcode();
20782 case ARMISD::LSRL: {
20786 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20788 unsigned ShAmt =
Op->getConstantOperandVal(2);
20798 case ARMISD::VBICIMM: {
20800 unsigned ModImm =
Op.getConstantOperandVal(1);
20801 unsigned EltBits = 0;
20803 if ((OriginalDemandedBits & Mask) == 0)
20809 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
20824 if (!Subtarget->hasVFP2Base())
20828 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20840 unsigned S = Constraint.
size();
20842 switch (Constraint[0]) {
20854 }
else if (S == 2) {
20855 switch (Constraint[0]) {
20872 Value *CallOperandVal =
info.CallOperandVal;
20875 if (!CallOperandVal)
20879 switch (*constraint) {
20885 if (Subtarget->isThumb())
20900 if (PR == 0 || VT == MVT::Other)
20902 if (ARM::SPRRegClass.
contains(PR))
20903 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20904 if (ARM::DPRRegClass.
contains(PR))
20909using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20913 switch (Constraint.
size()) {
20916 switch (Constraint[0]) {
20918 if (Subtarget->isThumb())
20919 return RCPair(0U, &ARM::tGPRRegClass);
20920 return RCPair(0U, &ARM::GPRRegClass);
20922 if (Subtarget->isThumb())
20923 return RCPair(0U, &ARM::hGPRRegClass);
20926 if (Subtarget->isThumb1Only())
20927 return RCPair(0U, &ARM::tGPRRegClass);
20928 return RCPair(0U, &ARM::GPRRegClass);
20930 if (VT == MVT::Other)
20932 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20933 return RCPair(0U, &ARM::SPRRegClass);
20935 return RCPair(0U, &ARM::DPRRegClass);
20937 return RCPair(0U, &ARM::QPRRegClass);
20940 if (VT == MVT::Other)
20942 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20943 return RCPair(0U, &ARM::SPR_8RegClass);
20945 return RCPair(0U, &ARM::DPR_8RegClass);
20947 return RCPair(0U, &ARM::QPR_8RegClass);
20950 if (VT == MVT::Other)
20952 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20953 return RCPair(0U, &ARM::SPRRegClass);
20955 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20957 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20963 if (Constraint[0] ==
'T') {
20964 switch (Constraint[1]) {
20968 return RCPair(0U, &ARM::tGPREvenRegClass);
20970 return RCPair(0U, &ARM::tGPROddRegClass);
20979 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20980 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20983 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20984 Constraint =
"{lr}";
20988 return {0,
nullptr};
20996 std::vector<SDValue> &
Ops,
21001 if (Constraint.
size() != 1)
21004 char ConstraintLetter = Constraint[0];
21005 switch (ConstraintLetter) {
21008 case 'I':
case 'J':
case 'K':
case 'L':
21009 case 'M':
case 'N':
case 'O':
21014 int64_t CVal64 =
C->getSExtValue();
21015 int CVal = (int) CVal64;
21018 if (CVal != CVal64)
21021 switch (ConstraintLetter) {
21025 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
21026 if (CVal >= 0 && CVal <= 65535)
21030 if (Subtarget->isThumb1Only()) {
21033 if (CVal >= 0 && CVal <= 255)
21035 }
else if (Subtarget->isThumb2()) {
21049 if (Subtarget->isThumb1Only()) {
21054 if (CVal >= -255 && CVal <= -1)
21060 if (CVal >= -4095 && CVal <= 4095)
21066 if (Subtarget->isThumb1Only()) {
21073 }
else if (Subtarget->isThumb2()) {
21093 if (Subtarget->isThumb1Only()) {
21096 if (CVal >= -7 && CVal < 7)
21098 }
else if (Subtarget->isThumb2()) {
21118 if (Subtarget->isThumb1Only()) {
21121 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
21127 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
21133 if (Subtarget->isThumb1Only()) {
21135 if (CVal >= 0 && CVal <= 31)
21141 if (Subtarget->isThumb1Only()) {
21144 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
21153 if (Result.getNode()) {
21154 Ops.push_back(Result);
21164 "Unhandled Opcode in getDivRemLibcall");
21170 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
21171 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
21172 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
21173 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
21180 const AttributeList &FuncAttrs, RTLIB::LibcallImpl LCImpl) {
21183 "Unhandled Opcode in getDivRemArgList");
21184 SDValue Ops[2] = {
N->getOperand(0),
N->getOperand(1)};
21188 case RTLIB::impl___rt_sdiv:
21189 case RTLIB::impl___rt_udiv:
21190 case RTLIB::impl___rt_sdiv64:
21191 case RTLIB::impl___rt_udiv64:
21202 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
21203 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
21204 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
21205 "Register-based DivRem lowering only");
21206 unsigned Opcode =
Op->getOpcode();
21208 "Invalid opcode for Div/Rem lowering");
21210 EVT VT =
Op->getValueType(0);
21230 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
21231 : Subtarget->hasDivideInARMMode();
21232 if (hasDivide &&
Op->getValueType(0).isSimple() &&
21233 Op->getSimpleValueType(0) == MVT::i32) {
21235 const SDValue Dividend =
Op->getOperand(0);
21236 const SDValue Divisor =
Op->getOperand(1);
21237 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
21241 SDValue
Values[2] = {Div, Rem};
21248 if (LCImpl == RTLIB::Unsupported)
21251 auto [FuncTy, FuncAttrs] =
21255 Type *RetTy = FuncTy->getReturnType();
21265 if (
getTM().getTargetTriple().isOSWindows())
21268 TargetLowering::CallLoweringInfo CLI(DAG);
21272 Callee, std::move(Args))
21277 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
21278 return CallInfo.first;
21284 EVT VT =
N->getValueType(0);
21290 Result[0], Result[1]);
21296 if (LCImpl == RTLIB::Unsupported)
21299 auto [FuncTy, FuncAttrs] =
21303 Type *RetTy = FuncTy->getReturnType();
21313 if (
getTM().getTargetTriple().isOSWindows())
21320 Callee, std::move(Args))
21324 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
21327 SDNode *ResNode = CallResult.first.getNode();
21334 assert(
getTM().getTargetTriple().isOSWindows() &&
21335 "unsupported target platform");
21339 SDValue Chain =
Op.getOperand(0);
21340 SDValue
Size =
Op.getOperand(1);
21343 "no-stack-arg-probe")) {
21347 Chain =
SP.getValue(1);
21353 SDValue
Ops[2] = {
SP, Chain };
21364 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
21365 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
21370 SDValue
Ops[2] = { NewSP, Chain };
21375 bool IsStrict =
Op->isStrictFPOpcode();
21376 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21377 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21379 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
21380 "Unexpected type for custom-lowering FP_EXTEND");
21382 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21383 "With both FP DP and 16, any FP conversion is legal!");
21385 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
21386 "With FP16, 16 to 32 conversion is legal!");
21389 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
21394 Loc,
Op.getValueType(), SrcVal);
21408 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
21409 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
21410 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
21411 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
21412 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
21416 {DstVT, MVT::Other}, {Chain, SrcVal});
21423 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21424 "Unexpected type for custom-lowering FP_EXTEND");
21425 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21430 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
21434 bool IsStrict =
Op->isStrictFPOpcode();
21436 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21438 EVT DstVT =
Op.getValueType();
21440 if (DstVT == MVT::bf16) {
21441 if (Subtarget->hasBF16() && SrcVT == MVT::f32)
21446 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21449 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
21450 "Unexpected type for custom-lowering FP_ROUND");
21452 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21453 "With both FP DP and 16, any FP conversion is legal!");
21458 if (SrcSz == 32 && Subtarget->hasFP16())
21463 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21464 "Unexpected type for custom-lowering FP_ROUND");
21466 SDValue Chain = IsStrict ?
Op.getOperand(0) : SDValue();
21468 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21480 if (v == 0xffffffff)
21491 bool ForCodeSize)
const {
21492 if (!Subtarget->hasVFP3Base())
21494 if (VT == MVT::f16 && Subtarget->hasFullFP16())
21497 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
21500 if (VT == MVT::f32)
21503 if (VT == MVT::f64 && Subtarget->hasFP64())
21511 bool ForCodeSize)
const {
21512 if (Subtarget->useSoftFloat() || !Subtarget->hasVFP2Base())
21525 case Intrinsic::arm_neon_vld1:
21526 case Intrinsic::arm_neon_vld2:
21527 case Intrinsic::arm_neon_vld3:
21528 case Intrinsic::arm_neon_vld4:
21529 case Intrinsic::arm_neon_vld2lane:
21530 case Intrinsic::arm_neon_vld3lane:
21531 case Intrinsic::arm_neon_vld4lane:
21532 case Intrinsic::arm_neon_vld2dup:
21533 case Intrinsic::arm_neon_vld3dup:
21534 case Intrinsic::arm_neon_vld4dup: {
21537 auto &
DL =
I.getDataLayout();
21538 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21540 Info.ptrVal =
I.getArgOperand(0);
21542 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21549 case Intrinsic::arm_neon_vld1x2:
21550 case Intrinsic::arm_neon_vld1x3:
21551 case Intrinsic::arm_neon_vld1x4: {
21554 auto &
DL =
I.getDataLayout();
21555 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21557 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
21559 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
21565 case Intrinsic::arm_neon_vst1:
21566 case Intrinsic::arm_neon_vst2:
21567 case Intrinsic::arm_neon_vst3:
21568 case Intrinsic::arm_neon_vst4:
21569 case Intrinsic::arm_neon_vst2lane:
21570 case Intrinsic::arm_neon_vst3lane:
21571 case Intrinsic::arm_neon_vst4lane: {
21574 auto &
DL =
I.getDataLayout();
21575 unsigned NumElts = 0;
21576 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21577 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21580 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21583 Info.ptrVal =
I.getArgOperand(0);
21585 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21592 case Intrinsic::arm_neon_vst1x2:
21593 case Intrinsic::arm_neon_vst1x3:
21594 case Intrinsic::arm_neon_vst1x4: {
21597 auto &
DL =
I.getDataLayout();
21598 unsigned NumElts = 0;
21599 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21600 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21603 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21606 Info.ptrVal =
I.getArgOperand(0);
21608 Info.align =
I.getParamAlign(0).valueOrOne();
21614 case Intrinsic::arm_mve_vld2q:
21615 case Intrinsic::arm_mve_vld4q: {
21619 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21621 Info.ptrVal =
I.getArgOperand(0);
21629 case Intrinsic::arm_mve_vst2q:
21630 case Intrinsic::arm_mve_vst4q: {
21633 Type *VecTy =
I.getArgOperand(1)->getType();
21634 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21636 Info.ptrVal =
I.getArgOperand(0);
21644 case Intrinsic::arm_mve_vldr_gather_base:
21645 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21647 Info.ptrVal =
nullptr;
21649 Info.align =
Align(1);
21654 case Intrinsic::arm_mve_vldr_gather_base_wb:
21655 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21657 Info.ptrVal =
nullptr;
21658 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21659 Info.align =
Align(1);
21664 case Intrinsic::arm_mve_vldr_gather_offset:
21665 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21667 Info.ptrVal =
nullptr;
21672 Info.align =
Align(1);
21677 case Intrinsic::arm_mve_vstr_scatter_base:
21678 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21680 Info.ptrVal =
nullptr;
21681 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21682 Info.align =
Align(1);
21687 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21688 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21690 Info.ptrVal =
nullptr;
21691 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21692 Info.align =
Align(1);
21697 case Intrinsic::arm_mve_vstr_scatter_offset:
21698 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21700 Info.ptrVal =
nullptr;
21705 Info.align =
Align(1);
21710 case Intrinsic::arm_ldaex:
21711 case Intrinsic::arm_ldrex: {
21712 auto &
DL =
I.getDataLayout();
21713 Type *ValTy =
I.getParamElementType(0);
21716 Info.ptrVal =
I.getArgOperand(0);
21718 Info.align =
DL.getABITypeAlign(ValTy);
21723 case Intrinsic::arm_stlex:
21724 case Intrinsic::arm_strex: {
21725 auto &
DL =
I.getDataLayout();
21726 Type *ValTy =
I.getParamElementType(1);
21729 Info.ptrVal =
I.getArgOperand(1);
21731 Info.align =
DL.getABITypeAlign(ValTy);
21736 case Intrinsic::arm_stlexd:
21737 case Intrinsic::arm_strexd:
21739 Info.memVT = MVT::i64;
21740 Info.ptrVal =
I.getArgOperand(2);
21742 Info.align =
Align(8);
21747 case Intrinsic::arm_ldaexd:
21748 case Intrinsic::arm_ldrexd:
21750 Info.memVT = MVT::i64;
21751 Info.ptrVal =
I.getArgOperand(0);
21753 Info.align =
Align(8);
21767 assert(Ty->isIntegerTy());
21769 unsigned Bits = Ty->getPrimitiveSizeInBits();
21770 if (Bits == 0 || Bits > 32)
21777 unsigned Index)
const {
21789 if (!Subtarget->hasDataBarrier()) {
21793 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21794 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21795 Builder.getInt32(0), Builder.getInt32(7),
21796 Builder.getInt32(10), Builder.getInt32(5)};
21797 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_mcr,
args);
21806 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::arm_dmb, CDomain);
21827 if (Subtarget->preferISHSTBarriers())
21860 bool has64BitAtomicStore;
21861 if (Subtarget->isMClass())
21862 has64BitAtomicStore =
false;
21863 else if (Subtarget->isThumb())
21864 has64BitAtomicStore = Subtarget->hasV7Ops();
21866 has64BitAtomicStore = Subtarget->hasV6Ops();
21868 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21882 bool has64BitAtomicLoad;
21883 if (Subtarget->isMClass())
21884 has64BitAtomicLoad =
false;
21885 else if (Subtarget->isThumb())
21886 has64BitAtomicLoad = Subtarget->hasV7Ops();
21888 has64BitAtomicLoad = Subtarget->hasV6Ops();
21904 if (Subtarget->isMClass())
21905 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21906 else if (Subtarget->isThumb())
21907 hasAtomicRMW = Subtarget->hasV7Ops();
21909 hasAtomicRMW = Subtarget->hasV6Ops();
21910 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21934 bool HasAtomicCmpXchg;
21935 if (Subtarget->isMClass())
21936 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21937 else if (Subtarget->isThumb())
21938 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21940 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21942 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21949 return InsertFencesForAtomic;
21954 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21960 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21961 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21963 RTLIB::LibcallImpl SecurityCookieVar =
21964 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21965 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21966 SecurityCookieVar != RTLIB::Unsupported) {
21977 F->addParamAttr(0, Attribute::AttrKind::InReg);
21984 unsigned &
Cost)
const {
21986 if (!Subtarget->hasNEON())
22015 unsigned Opcode =
Op.getOpcode();
22017 case ARMISD::VORRIMM:
22018 case ARMISD::VBICIMM:
22022 Op, DemandedElts, DAG, Kind, ConsiderFlags,
Depth);
22026 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
22030 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
22035 if (!Subtarget->hasV7Ops())
22041 if (!Mask || Mask->getValue().getBitWidth() > 32u)
22043 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
22051 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
22060 Module *M = Builder.getModule();
22066 if (ValueTy->getPrimitiveSizeInBits() == 64) {
22068 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
22071 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
22073 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
22074 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
22075 if (!Subtarget->isLittle())
22077 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
22078 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
22079 return Builder.CreateOr(
22080 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
22084 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
22085 CallInst *CI = Builder.CreateIntrinsicWithoutFolding(
Int, Tys, Addr);
22088 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
22089 return Builder.CreateTruncOrBitCast(CI, ValueTy);
22094 if (!Subtarget->hasV7Ops())
22096 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
22102 Module *M = Builder.getModule();
22110 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
22113 Value *
Lo = Builder.CreateTrunc(Val, Int32Ty,
"lo");
22114 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32), Int32Ty,
"hi");
22115 if (!Subtarget->isLittle())
22117 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
22120 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
22124 CallInst *CI = Builder.CreateCall(
22125 Strex, {Builder.CreateZExtOrBitCast(
22135 return Subtarget->isMClass();
22143 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
22150 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
22153 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
22161 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
22169 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
22172 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
22177 if (Subtarget->hasNEON() && VecSize == 64)
22179 return VecSize % 128 == 0;
22183 if (Subtarget->hasNEON())
22185 if (Subtarget->hasMVEIntegerOps())
22205 "Invalid interleave factor");
22206 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
22208 "Unmatched number of shufflevectors and indices");
22213 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
22216 Type *EltTy = VecTy->getElementType();
22219 Align Alignment = LI->getAlign();
22237 Value *BaseAddr = LI->getPointerOperand();
22239 if (NumLoads > 1) {
22243 VecTy->getNumElements() / NumLoads);
22249 if (Subtarget->hasNEON()) {
22250 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
22251 Type *Tys[] = {VecTy, PtrTy};
22252 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
22253 Intrinsic::arm_neon_vld3,
22254 Intrinsic::arm_neon_vld4};
22257 Ops.push_back(BaseAddr);
22258 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
22260 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
22263 assert((Factor == 2 || Factor == 4) &&
22264 "expected interleave factor of 2 or 4 for MVE");
22266 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
22267 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
22268 Type *Tys[] = {VecTy, PtrTy};
22271 Ops.push_back(BaseAddr);
22272 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
22282 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
22286 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
22287 VecTy->getNumElements() * Factor);
22293 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
22295 unsigned Index = Indices[i];
22297 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
22301 SubVec = Builder.CreateIntToPtr(
22305 SubVecs[SV].push_back(SubVec);
22314 auto &SubVec = SubVecs[SVI];
22317 SVI->replaceAllUsesWith(WideVec);
22353 const APInt &GapMask)
const {
22355 "Invalid interleave factor");
22360 "Unexpected mask on store");
22363 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
22365 unsigned LaneLen = VecTy->getNumElements() / Factor;
22366 Type *EltTy = VecTy->getElementType();
22370 Align Alignment =
SI->getAlign();
22387 Type *IntTy =
DL.getIntPtrType(EltTy);
22392 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
22393 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
22399 Value *BaseAddr =
SI->getPointerOperand();
22401 if (NumStores > 1) {
22404 LaneLen /= NumStores;
22414 if (Subtarget->hasNEON()) {
22415 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
22416 Intrinsic::arm_neon_vst3,
22417 Intrinsic::arm_neon_vst4};
22418 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22419 Type *Tys[] = {PtrTy, SubVecTy};
22422 Ops.push_back(BaseAddr);
22424 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
22425 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
22427 assert((Factor == 2 || Factor == 4) &&
22428 "expected interleave factor of 2 or 4 for MVE");
22430 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
22431 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22432 Type *Tys[] = {PtrTy, SubVecTy};
22435 Ops.push_back(BaseAddr);
22437 for (
unsigned F = 0;
F < Factor;
F++) {
22438 Ops.push_back(Builder.getInt32(
F));
22439 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
22445 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
22448 if (StoreCount > 0)
22449 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
22450 BaseAddr, LaneLen * Factor);
22455 for (
unsigned i = 0; i < Factor; i++) {
22456 unsigned IdxI = StoreCount * LaneLen * Factor + i;
22457 if (Mask[IdxI] >= 0) {
22458 Shuffles.
push_back(Builder.CreateShuffleVector(
22461 unsigned StartMask = 0;
22462 for (
unsigned j = 1; j < LaneLen; j++) {
22463 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
22464 if (Mask[IdxJ * Factor + IdxI] >= 0) {
22465 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
22475 Shuffles.
push_back(Builder.CreateShuffleVector(
22496 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
22500 Members += SubMembers;
22506 Members += SubMembers * AT->getNumElements();
22507 }
else if (Ty->isFloatTy()) {
22512 }
else if (Ty->isDoubleTy()) {
22524 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
22526 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
22528 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
22541 return (Members > 0 && Members <= 4);
22547 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
22549 return ABITypeAlign;
22554 assert(StackAlign &&
"data layout string is missing stack alignment");
22555 return std::min(ABITypeAlign, *StackAlign);
22569 uint64_t Members = 0;
22573 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
22574 return IsHA || IsIntArray;
22597void ARMTargetLowering::insertCopiesSplitCSR(
22601 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22611 RC = &ARM::GPRRegClass;
22612 else if (ARM::DPRRegClass.
contains(*
I))
22613 RC = &ARM::DPRRegClass;
22623 assert(Entry->getParent()->getFunction().hasFnAttribute(
22624 Attribute::NoUnwind) &&
22625 "Function should be nounwind in insertCopiesSplitCSR!");
22626 Entry->addLiveIn(*
I);
22631 for (
auto *Exit : Exits)
22633 TII->get(TargetOpcode::COPY), *
I)
22644 return Subtarget->hasMVEIntegerOps();
22654 unsigned NumElements = VTy->getNumElements();
22661 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22662 return Subtarget->hasMVEFloatOps();
22667 return Subtarget->hasMVEIntegerOps() &&
22668 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22669 ScalarTy->isIntegerTy(32));
22673 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22684 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22686 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22688 if (TyWidth > 128) {
22689 int Stride = Ty->getNumElements() / 2;
22693 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22695 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22696 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22697 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22698 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22699 Value *LowerSplitAcc =
nullptr;
22700 Value *UpperSplitAcc =
nullptr;
22703 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22704 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22708 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22710 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22712 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22713 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22720 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22723 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22725 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22726 {ConstRotation, InputB, InputA});
22731 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22734 ConstRotation = ConstantInt::get(IntTy, 0);
22736 ConstRotation = ConstantInt::get(IntTy, 1);
22738 if (!ConstRotation)
22741 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22742 {ConstHalving, ConstRotation, InputA, InputB});
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static SDValue carryFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG, bool Invert)
static SDValue overflowFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue valueToCarryFlag(SDValue Value, SelectionDAG &DAG, bool Invert)
constexpr MVT FlagsVT
Value type used for NZCV flags.
static unsigned getCmpOperandFoldingProfit(SDValue Op, bool AllowExtend)
Returns how profitable it is to fold a comparison's operand's shift and/or extension operations.
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static bool optimizeLogicalImm(SDValue Op, unsigned Size, uint64_t Imm, const APInt &Demanded, TargetLowering::TargetLoweringOpt &TLO, unsigned NewOpc)
static bool isSafeSignedCMN(SDValue Op, SelectionDAG &DAG)
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVECTOR_DEINTERLEAVECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static SDValue PerformLegalizedVECTOR_DEINTERLEAVECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, FunctionType *FuncTy, const AttributeList &FuncAttrs, RTLIB::LibcallImpl LCImpl)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformInterleavedStoreCombine(StoreSDNode *ST, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static SDValue matchCSET(unsigned &Opcode, bool &InvertCond, SDValue TrueVal, SDValue FalseVal, const ARMSubtarget *Subtarget)
static bool isSequentialConcatOfVectorInterleave(SDNode *N, SmallVectorImpl< SDValue > &Ops)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getInvertedARMCondCode(SDValue ARMcc, SelectionDAG &DAG)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static SDValue LowerADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG, unsigned Opcode, bool IsSigned)
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static int getNegationCost(SDValue Op)
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static bool isLegalLogicalImmediate(unsigned Imm, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue GeneratePerfectShuffle(unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &dl)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static SDValue PerformLegalizedInterleavedStoreCombine(StoreSDNode *ST, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerTruncate(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformHWLoopCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformORCombineToShiftInsert(SelectionDAG &DAG, SDValue AndOp, SDValue ShiftOp, EVT VT, SDLoc dl)
static SDValue PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue getShiftedLowMaskZeroTest(SDValue Value, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
arm ldst static false bool definesCPSR(const MachineInstr &MI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
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")))
Contains matchers for matching SelectionDAG nodes and values.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static constexpr roundingMode rmTowardZero
LLVM_ABI bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
unsigned logBase2() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool isOne() const
Determine if this is a value of 1.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
const ARMBaseRegisterInfo & getRegisterInfo() const
const uint32_t * getSjLjDispatchPreservedMask(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const uint32_t * getTLSCallPreservedMask(const MachineFunction &MF) const
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj, ARMCP::ARMCPModifier Modifier=ARMCP::no_modifier, bool AddCurrentAddress=false)
ARMConstantPoolValue - ARM specific constantpool value.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
int getVarArgsFrameIndex() const
SmallVectorImpl< ForwardedRegister > & getForwardedMustTailRegParms()
int getPromotedConstpoolIncrease() const
SmallPtrSet< const GlobalVariable *, 2 > & getGlobalsPromotedToConstantPool()
void setArgumentStackToRestore(unsigned v)
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
void setPromotedConstpoolIncrease(int Sz)
bool isThumb1OnlyFunction() const
void setArgRegsSaveSize(unsigned s)
bool isCmseNSEntryFunction() const
void setReturnRegsCount(unsigned s)
void setVarArgsFrameIndex(int Index)
unsigned getArgRegsSaveSize() const
void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV)
Indicate to the backend that GV has had its storage changed to inside a constant pool.
void setIsSplitCSR(bool s)
void setArgumentStackSize(unsigned size)
unsigned getArgumentStackSize() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool isReadOnly(const GlobalValue *GV) const
unsigned getMaxSupportedInterleaveFactor() const override
Get the maximum supported factor for interleaved memory accesses.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
unsigned getNumInterleavedAccesses(VectorType *VecTy, const DataLayout &DL) const
Returns the number of interleaved accesses that will be generated when lowering accesses of the given...
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Align getABIAlignmentForCallingConv(Type *ArgTy, const DataLayout &DL) const override
Return the correct alignment for the current calling convention.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const
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...
FPImmAction getFPImmAction(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const override
Returns how to materialize the specified FP immediate.
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
bool shouldFoldConstantShiftPairToMask(const SDNode *N) const override
Return true if it is profitable to fold a pair of shifts into a mask.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override
Return true if it is profitable to combine an XOR of a logical shift to create a logical shift of NOT...
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const
PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
Value * createComplexDeinterleavingIR(IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, Value *Accumulator=nullptr) const override
Create the IR node for the given complex deinterleaving operation.
bool isComplexDeinterleavingSupported() const override
Does this target support complex deinterleaving.
SDValue PerformMVEExtCombine(SDNode *N, DAGCombinerInfo &DCI) const
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const override
Inserts necessary declarations for SSP (stack protection) purpose.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &OriginalDemandedBits, const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the value type to use for ISD::SETCC.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const override
Perform a store-conditional operation to Addr.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool isVarArg) const
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
isShuffleMaskLegal - Targets can use this to indicate that they only support some VECTOR_SHUFFLE oper...
Register getExceptionPointerRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
bool lowerInterleavedStore(Instruction *Store, Value *Mask, ShuffleVectorInst *SVI, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved store into a vstN intrinsic.
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
bool useLoadStackGuardNode(const Module &M) const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vldN intrinsic.
std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override
Return the largest legal super-reg register class of the register class for the specified type and it...
bool preferSelectsOverBooleanArithmetic(EVT VT) const override
Should we prefer selects to doing arithmetic on boolean types.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
Register getExceptionSelectorRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of EXTRACT_SUBVECTOR for this result type with this index.
CallingConv::ID getEffectiveCallingConv(CallingConv::ID CC, bool isVarArg) const
getEffectiveCallingConv - Get the effective calling convention, taking into account presence of float...
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
bool supportKCFIBundles() const override
Return true if the target supports kcfi operand bundles.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool isVarArg) const
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
allowsMisalignedMemoryAccesses - Returns true if the target allows unaligned memory accesses of the s...
bool isLegalInterleavedAccessType(unsigned Factor, FixedVectorType *VecTy, Align Alignment, const DataLayout &DL) const
Returns true if VecTy is a legal interleaved access type.
bool isVectorLoadExtDesirable(SDValue ExtVal) const override
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, unsigned &Cost) const override
Return true if the target can combine store(extractelement VectorTy,Idx).
bool useSoftFloat() const override
bool alignLoopsWithOptSize() const override
Should loops be aligned even when the function is marked OptSize (but not MinSize).
SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const
bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override
Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail ...
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
bool hasAndNotCompare(SDValue V) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT.
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
bool isFloatingPointOperation() const
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
The address of a basic block.
static constexpr BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
LLVM_ABI int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, uint32_t BitWidth) const
If this is a constant FP splat and the splatted constant FP is an exact power or 2,...
CCState - This class holds information needed while lowering arguments and return values.
void getInRegsParamInfo(unsigned InRegsParamRecordIndex, unsigned &BeginReg, unsigned &EndReg) const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void analyzeMustTailForwardedRegisters(SmallVectorImpl< ForwardedRegister > &Forwards, ArrayRef< MVT > RegParmTypes, CCAssignFn Fn)
Compute the set of registers that need to be preserved and forwarded to any musttail calls.
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
void rewindByValRegsInfo()
unsigned getInRegsParamsProcessed() const
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd)
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
unsigned getInRegsParamsCount() const
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
const APFloat & getValueAPF() const
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
MachineConstantPoolValue * getMachineCPVal() const
bool isMachineConstantPoolEntry() const
const Constant * getConstVal() const
LLVM_ABI Type * getType() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
MaybeAlign getStackAlignment() const
Returns the natural stack alignment, or MaybeAlign() if one wasn't specified.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
StringRef getInternalSymbolPrefix() const
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
Tracks which library functions to use for a particular subtarget or function.
const RTLIB::RuntimeLibcallsInfo & getRuntimeLibcallsInfo() const
CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const
Get the CallingConv that should be used for the specified libcall.
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Describe properties that are true of each instruction in the target description file.
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
bool is64BitVector() const
Return true if this is a 64-bit vector type.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
bool hasMustTailInVarArgFunc() const
Returns true if the function is variadic and contains a musttail call.
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI unsigned createJumpTableIndex(const std::vector< MachineBasicBlock * > &DestBBs)
createJumpTableIndex - Create a new jump table.
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
This class is used to represent an MLOAD node.
This class is used to represent an MSTORE node.
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
op_iterator op_end() const
op_iterator op_begin() const
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
LLVM_ABI SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI bool areNonVolatileConsecutiveLoads(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, int Dist) const
Return true if loads are next to each other and can be merged.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
const LibcallLoweringInfo & getLibcalls() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI OverflowKind computeOverflowForSignedAdd(SDValue N0, SDValue N1) const
Determine if the result of the signed addition of 2 nodes can overflow.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI bool areNonVolatileConsecutiveStores(StoreSDNode *ST, StoreSDNode *Base, unsigned Bytes, int Dist) const
Return true if stores are next to each other and can be merged.
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
Represent a constant reference to a string, i.e.
const unsigned char * bytes_end() const
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
const unsigned char * bytes_begin() const
TargetInstrInfo - Interface to description of machine instruction set.
Provides information about what library functions are available for the current target.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
ShiftLegalizationStrategy
Return the preferred strategy to legalize tihs SHIFT instruction, with ExpansionFactor being the recu...
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
const TargetMachine & getTargetMachine() const
virtual void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const
Inserts necessary declarations for SSP (stack protection) purpose.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const
Returns true if the specified FP immediate can be materialized without a load from the constant pool.
void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked load does or does not work with the specified type and ind...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked store does or does not work with the specified type and in...
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
FPImmAction
How the legalizer should materialize a floating-point immediate.
@ ConstantPool
Load the immediate from the constant pool.
@ Legal
The target can instruction select the immediate natively.
@ Bitcast
Build the immediate as a bitcast of an integer constant with the same bits.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
static StringRef getLibcallImplName(RTLIB::LibcallImpl Call)
Get the libcall routine name for the specified libcall implementation.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool expandDIVREMByConstant(SDNode *N, SmallVectorImpl< SDValue > &Result, EVT HiLoVT, SelectionDAG &DAG, SDValue LL=SDValue(), SDValue LH=SDValue()) const
Attempt to expand an n-bit div/rem/divrem by constant using an n/2-bit algorithm.
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
static ArgListTy getArgListForFunctionType(FunctionType *FuncTy, const AttributeList &FuncAttrs, ArrayRef< SDValue > Ops)
Build a call argument list for FuncTy, taking the argument node values from Ops and the parameter typ...
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual ArrayRef< MCPhysReg > getRoundingControlRegisters() const
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
void setTypeIdForCallsiteInfo(const CallBase *CB, MachineFunction &MF, MachineFunction::CallSiteInfo &CSInfo) const
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
Base class of all SIMD vector types.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static CondCodes getOppositeCondition(CondCodes CC)
static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC)
getSwappedCondition - assume the flags are set by MI(a,b), return the condition code if we modify the...
@ SECREL
Thread Pointer Offset.
@ GOT_PREL
Thread Local Storage (General Dynamic Mode)
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
TOF
Target Operand Flag enum.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2Offset(unsigned AM2Opc)
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
AddrOpc getAM2Op(unsigned AM2Opc)
bool isBitFieldInvertedMask(unsigned v)
const unsigned FPStatusBits
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
const unsigned FPReservedBits
const unsigned RoundingBitsPos
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Swift
Calling convention for Swift.
@ ARM_APCS
ARM Procedure Calling Standard (obsolete, but still used on some targets).
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ ARM_AAPCS
ARM Architecture Procedure Calling Standard calling convention (aka EABI).
@ CXX_FAST_TLS
Used for access functions.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ ARM_AAPCS_VFP
Same as ARM_AAPCS, but uses hard floating point ABI.
@ C
The default llvm calling convention, compatible with C.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ POISON
POISON - A poison node.
@ SET_FPENV
Sets the current floating-point environment.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
@ FGETSIGN
INT = FGETSIGN(FP) - Return the sign bit of the specified floating point value as an integer 0/1 valu...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ RESET_FPENV
Set floating-point environment to default state.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SET_FPMODE
Sets the current dynamic floating-point control modes.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ EH_SJLJ_SETUP_DISPATCH
OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) The target initializes the dispatch table here.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ RESET_FPMODE
Sets default dynamic floating-point control modes.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ BR
Control flow instructions. These all have token chains.
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ BR_JT
BR_JT - Jumptable branch.
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ SMULO
Same for multiplication.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FMINIMUM
FMINIMUM/FMAXIMUM - Same semantics as the llvm.minimum/maximum intrinsics.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ SADDO_CARRY
Carry-using overflow-aware nodes for multiple precision addition and subtraction.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
auto m_Value()
Match an arbitrary value and ignore it.
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.
bool sd_match(SDValue N, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
void stable_sort(R &&Range)
bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
const unsigned PerfectShuffleTable[6561+1]
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
@ SjLj
setjmp/longjmp based exceptions
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
UndefPoisonKind
Enumeration to track whether we are interested in Undef, Poison, or both.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr Align fromLog2(unsigned Log2Value)
Returns an alignment of 1 << Log2Value bytes.
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 ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
LLVM_ABI std::pair< FunctionType *, AttributeList > getFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL, RTLIB::LibcallImpl LibcallImpl) const
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
CombineLevel getDAGCombineLevel()
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
LLVM_ABI bool recursivelyDeleteUnusedNodes(SDNode *N)
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)