83#include "llvm/IR/IntrinsicsARM.h"
118#define DEBUG_TYPE "arm-isel"
121STATISTIC(NumOptimizedImms,
"Number of times immediates were optimized");
122STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
123STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
125 "Number of constants with their storage promoted into constant pools");
129 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
134 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
139 cl::desc(
"Maximum size of constant to promote into a constant pool"),
143 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
148 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
153 cl::desc(
"Maximum number of base-updates to check generating postindex."),
161 ARM::R0, ARM::R1, ARM::R2, ARM::R3
175void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
176 if (VT != PromotedLdStVT) {
185 if (ElemTy != MVT::f64)
189 if (ElemTy == MVT::i32) {
233void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
235 addTypeForNEON(VT, MVT::f64);
238void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
240 addTypeForNEON(VT, MVT::v2f64);
243void ARMTargetLowering::setAllExpand(
MVT VT) {
256void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
263void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
264 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
266 for (
auto VT : IntTypes) {
341 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
342 for (
auto VT : FloatTypes) {
416 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
417 for (
auto VT : LongTypes) {
434 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
435 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
436 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
453 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
462 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
463 for (
auto VT : pTypes) {
514 RegInfo(Subtarget->getRegisterInfo()),
515 Itins(Subtarget->getInstrItineraryData()) {
521 const Triple &TT = TM.getTargetTriple();
523 if (Subtarget->isThumb1Only())
528 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
529 Subtarget->hasFPRegs()) {
533 if (!Subtarget->hasVFP2Base()) {
534 setAllExpand(MVT::f32);
543 if (!Subtarget->hasFP64()) {
544 setAllExpand(MVT::f64);
554 if (Subtarget->hasFullFP16()) {
569 if (Subtarget->hasBF16()) {
571 setAllExpand(MVT::bf16);
572 if (!Subtarget->hasFullFP16())
584 addAllExtLoads(VT, InnerVT,
Expand);
593 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
596 if (!Subtarget->hasV8_1MMainlineOps())
599 if (!Subtarget->isThumb1Only())
608 if (Subtarget->hasMVEIntegerOps())
609 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
612 if (Subtarget->hasLOB()) {
616 if (Subtarget->hasNEON()) {
617 addDRTypeForNEON(MVT::v2f32);
618 addDRTypeForNEON(MVT::v8i8);
619 addDRTypeForNEON(MVT::v4i16);
620 addDRTypeForNEON(MVT::v2i32);
621 addDRTypeForNEON(MVT::v1i64);
623 addQRTypeForNEON(MVT::v4f32);
624 addQRTypeForNEON(MVT::v2f64);
625 addQRTypeForNEON(MVT::v16i8);
626 addQRTypeForNEON(MVT::v8i16);
627 addQRTypeForNEON(MVT::v4i32);
628 addQRTypeForNEON(MVT::v2i64);
630 if (Subtarget->hasFullFP16()) {
631 addQRTypeForNEON(MVT::v8f16);
632 addDRTypeForNEON(MVT::v4f16);
635 if (Subtarget->hasBF16()) {
636 addQRTypeForNEON(MVT::v8bf16);
637 addDRTypeForNEON(MVT::v4bf16);
641 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
681 if (Subtarget->hasNEON()) {
794 if (!Subtarget->hasVFP4Base()) {
803 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
812 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
821 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
829 if (Subtarget->hasMVEIntegerOps()) {
834 if (Subtarget->hasMVEFloatOps()) {
838 if (!Subtarget->hasFP64()) {
884 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
887 if (Subtarget->hasFullFP16()) {
895 if (!Subtarget->hasFP16()) {
924 if (!Subtarget->isThumb1Only()) {
943 if (TT.isTargetAEABI() && !Subtarget->allowsUnalignedMem()) {
955 if (!Subtarget->isThumb1Only()) {
964 if (Subtarget->hasDSP()) {
974 if (Subtarget->hasBaseDSP()) {
982 if (Subtarget->isThumb1Only()) {
986 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
987 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1002 if (Subtarget->hasMVEIntegerOps())
1006 if (Subtarget->isThumb1Only()) {
1012 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1026 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1035 if (Subtarget->hasPerfMon())
1039 if (!Subtarget->hasV6Ops())
1042 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1043 : Subtarget->hasDivideInARMMode();
1050 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1062 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1063 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1066 HasStandaloneRem =
false;
1093 if (TT.isOSWindows())
1100 InsertFencesForAtomic =
false;
1101 if (Subtarget->hasAnyDataBarrier() &&
1102 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1106 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1111 if (!Subtarget->hasAcquireRelease() ||
1114 InsertFencesForAtomic =
true;
1120 if (Subtarget->hasDataBarrier())
1121 InsertFencesForAtomic =
true;
1141 if (!InsertFencesForAtomic) {
1148 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1160 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1161 Subtarget->hasForced32BitAtomics()) {
1175 if (!Subtarget->hasV6Ops()) {
1181 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1182 !Subtarget->isThumb1Only()) {
1211 if (Subtarget->hasFullFP16()) {
1221 if (Subtarget->hasFullFP16())
1236 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1237 !Subtarget->isThumb1Only()) {
1244 if (!Subtarget->hasVFP4Base()) {
1250 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1252 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1260 if (!Subtarget->hasFP16()) {
1277 if (Subtarget->hasFPARMv8Base()) {
1287 if (Subtarget->hasFP64())
1291 if (Subtarget->hasNEON()) {
1301 if (Subtarget->hasFullFP16()) {
1338 if (Subtarget->hasNEON()) {
1350 if (Subtarget->hasV8Ops()) {
1360 if (Subtarget->hasFullFP16()) {
1383 if (TT.isOSWindows()) {
1400 if (Subtarget->hasMVEIntegerOps())
1403 if (Subtarget->hasV6Ops())
1405 if (Subtarget->isThumb1Only())
1408 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1409 Subtarget->isThumb2()) {
1415 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1416 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1438 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1446 return Subtarget->useSoftFloat();
1450 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1463std::pair<const TargetRegisterClass *, uint8_t>
1474 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1475 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1476 RRC = &ARM::DPRRegClass;
1481 if (Subtarget->useNEONForSinglePrecisionFP())
1484 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1485 case MVT::v4f32:
case MVT::v2f64:
1486 RRC = &ARM::DPRRegClass;
1490 RRC = &ARM::DPRRegClass;
1494 RRC = &ARM::DPRRegClass;
1498 return std::make_pair(RRC,
Cost);
1507 if (Subtarget->hasMVEIntegerOps())
1522 if (Subtarget->hasNEON()) {
1523 if (VT == MVT::v4i64)
1524 return &ARM::QQPRRegClass;
1525 if (VT == MVT::v8i64)
1526 return &ARM::QQQQPRRegClass;
1528 if (Subtarget->hasMVEIntegerOps()) {
1529 if (VT == MVT::v4i64)
1530 return &ARM::MQQPRRegClass;
1531 if (VT == MVT::v8i64)
1532 return &ARM::MQQQQPRRegClass;
1541 Align &PrefAlign)
const {
1548 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1560 unsigned NumVals =
N->getNumValues();
1564 for (
unsigned i = 0; i != NumVals; ++i) {
1565 EVT VT =
N->getValueType(i);
1566 if (VT == MVT::Glue || VT == MVT::Other)
1572 if (!
N->isMachineOpcode())
1580 if (
MCID.getNumDefs() == 0)
1582 if (!Itins->isEmpty() &&
1583 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1597 return Const->getZExtValue() == 16;
1605 return Const->getZExtValue() == 16;
1613 return Const->getZExtValue() == 16;
1682 bool isVarArg)
const {
1701 if (!
getTM().isAAPCS_ABI())
1703 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1711 if (!
getTM().isAAPCS_ABI()) {
1712 if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() && !isVarArg)
1715 }
else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1724 bool isVarArg)
const {
1725 return CCAssignFnForNode(CC,
false, isVarArg);
1729 bool isVarArg)
const {
1730 return CCAssignFnForNode(CC,
true, isVarArg);
1737 bool isVarArg)
const {
1738 switch (getEffectiveCallingConv(CC, isVarArg)) {
1764 if (Subtarget->hasFullFP16()) {
1765 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1777 if (Subtarget->hasFullFP16()) {
1778 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1791SDValue ARMTargetLowering::LowerCallResult(
1795 SDValue ThisVal,
bool isCmseNSCall)
const {
1803 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1804 CCValAssign VA = RVLocs[i];
1808 if (i == 0 && isThisReturn) {
1810 "unexpected return calling convention register assignment");
1828 if (!Subtarget->isLittle())
1830 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1845 if (!Subtarget->isLittle())
1847 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1877 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1888std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1890 bool IsTailCall,
int SPDiff)
const {
1892 MachinePointerInfo DstInfo;
1912 return std::make_pair(DstAddr, DstInfo);
1921ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1934 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1937 int SrcFI = SrcFrameIdxNode->getIndex();
1938 int DstFI = DstFrameIdxNode->getIndex();
1940 "byval passed in non-fixed stack slot");
1962 if (SrcOffset == DstOffset)
1970 RegsToPassVector &RegsToPass,
1977 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1978 unsigned id = Subtarget->isLittle() ? 0 : 1;
1990 MachinePointerInfo DstInfo;
1991 std::tie(DstAddr, DstInfo) =
1992 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2009 SelectionDAG &DAG = CLI.
DAG;
2011 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2012 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2013 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2020 const CallBase *CB = CLI.
CB;
2023 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2025 MachineFunction::CallSiteInfo CSInfo;
2026 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2027 bool isThisReturn =
false;
2028 bool isCmseNSCall =
false;
2029 bool isSibCall =
false;
2030 bool PreferIndirect =
false;
2031 bool GuardWithBTI =
false;
2041 !Subtarget->noBTIAtReturnTwice())
2049 isCmseNSCall =
true;
2052 if (!Subtarget->supportsTailCall())
2068 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2069 count_if(GV->users(), [&BB](
const User *U) {
2070 return isa<Instruction>(U) &&
2071 cast<Instruction>(U)->getParent() == BB;
2078 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2092 "site marked musttail");
2095 unsigned NumBytes = CCInfo.getStackSize();
2104 if (isTailCall && !isSibCall) {
2105 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2106 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2111 assert(StackAlign &&
"data layout string is missing stack alignment");
2112 NumBytes =
alignTo(NumBytes, *StackAlign);
2117 SPDiff = NumReusableBytes - NumBytes;
2121 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2137 RegsToPassVector RegsToPass;
2146 DenseMap<unsigned, SDValue> ByValTemporaries;
2150 for (
const CCValAssign &VA : ArgLocs) {
2152 SDValue Src = OutVals[ArgIdx];
2153 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2155 if (!
Flags.isByVal())
2159 MachinePointerInfo DstInfo;
2160 std::tie(Dst, DstInfo) =
2161 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2162 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2164 if (Copy == NoCopy) {
2169 }
else if (Copy == CopyOnce) {
2173 ByValTemporaries[ArgIdx] = Src;
2175 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2179 int TempFrameIdx = MFI.CreateStackObject(
2180 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2188 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2189 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2191 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2192 ByValTemporaries[ArgIdx] = Temp;
2195 if (!ByValCopyChains.
empty())
2205 bool AfterFormalArgLoads =
false;
2209 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2211 ++i, ++realArgIdx) {
2212 CCValAssign &VA = ArgLocs[i];
2213 SDValue Arg = OutVals[realArgIdx];
2214 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2215 bool isByVal =
Flags.isByVal();
2235 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2237 if (ByValTempChain) {
2242 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2243 if (Outs[
I].
Flags.isByVal())
2251 FrameIndexSDNode *FIN =
2256 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2259 for (
const CCValAssign &VA : ArgLocs) {
2267 if (!IncomingLoad.
empty()) {
2275 AfterFormalArgLoads =
true;
2287 auto ArgVT = Outs[realArgIdx].ArgVT;
2288 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2306 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2307 StackPtr, MemOpChains, isTailCall, SPDiff);
2311 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2312 StackPtr, MemOpChains, isTailCall, SPDiff);
2316 MachinePointerInfo DstInfo;
2317 std::tie(DstAddr, DstInfo) =
2318 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2322 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2323 StackPtr, MemOpChains, isTailCall, SPDiff);
2325 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2326 Outs[0].VT == MVT::i32) {
2328 "unexpected calling convention register assignment");
2330 "unexpected use of 'returned'");
2331 isThisReturn =
true;
2336 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2337 }
else if (isByVal) {
2339 unsigned offset = 0;
2343 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2344 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2347 bool NeedsStackCopy;
2348 if (
auto It = ByValTemporaries.
find(realArgIdx);
2349 It != ByValTemporaries.
end()) {
2350 ByValSrc = It->second;
2351 NeedsStackCopy =
true;
2354 NeedsStackCopy = !isTailCall;
2358 if (CurByValIdx < ByValArgsCount) {
2359 unsigned RegBegin, RegEnd;
2360 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2364 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2368 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2371 RegsToPass.push_back(std::make_pair(j, Load));
2376 offset = RegEnd - RegBegin;
2378 CCInfo.nextInRegsParam();
2383 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2386 MachinePointerInfo DstInfo;
2387 std::tie(Dst, DstInfo) =
2388 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2396 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2397 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2404 MachinePointerInfo DstInfo;
2405 std::tie(DstAddr, DstInfo) =
2406 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2413 if (!MemOpChains.
empty())
2419 for (
const auto &[
Reg,
N] : RegsToPass) {
2427 bool isDirect =
false;
2430 const Triple &
TT = TM.getTargetTriple();
2431 const GlobalValue *GVal =
nullptr;
2433 GVal =
G->getGlobal();
2434 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2436 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2437 bool isLocalARMFunc =
false;
2440 if (Subtarget->genLongCalls()) {
2442 "long-calls codegen is not position independent!");
2447 if (Subtarget->genExecuteOnly()) {
2448 if (Subtarget->useMovt())
2460 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2466 const char *Sym = S->getSymbol();
2468 if (Subtarget->genExecuteOnly()) {
2469 if (Subtarget->useMovt())
2481 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2488 if (!PreferIndirect) {
2493 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2495 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2496 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2498 ARMISD::WrapperPIC, dl, PtrVt,
2505 }
else if (Subtarget->isTargetCOFF()) {
2506 assert(Subtarget->isTargetWindows() &&
2507 "Windows is the only supported COFF target");
2511 else if (!TM.shouldAssumeDSOLocal(GVal))
2518 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2527 const char *Sym = S->getSymbol();
2528 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2530 ARMConstantPoolValue *CPV =
2532 ARMPCLabelIndex, 4);
2534 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2539 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2546 assert(!isARMFunc && !isDirect &&
2547 "Cannot handle call to ARM function or direct call");
2551 "call to non-secure function would require "
2552 "passing arguments on stack",
2558 "call to non-secure function would return value through pointer",
2565 if (Subtarget->isThumb()) {
2567 CallOpc = ARMISD::t2CALL_BTI;
2568 else if (isCmseNSCall)
2569 CallOpc = ARMISD::tSECALL;
2570 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2571 CallOpc = ARMISD::CALL_NOLINK;
2573 CallOpc = ARMISD::CALL;
2575 if (!isDirect && !Subtarget->hasV5TOps())
2576 CallOpc = ARMISD::CALL_NOLINK;
2577 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2579 !Subtarget->hasMinSize())
2581 CallOpc = ARMISD::CALL_NOLINK;
2583 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2590 if (isTailCall && !isSibCall) {
2595 std::vector<SDValue>
Ops;
2596 Ops.push_back(Chain);
2597 Ops.push_back(Callee);
2605 for (
const auto &[
Reg,
N] : RegsToPass)
2609 const uint32_t *
Mask;
2610 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2618 isThisReturn =
false;
2624 assert(Mask &&
"Missing call preserved mask for calling convention");
2628 Ops.push_back(InGlue);
2641 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2652 uint64_t CalleePopBytes =
2655 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2661 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2662 InVals, isThisReturn,
2663 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2670void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2671 Align Alignment)
const {
2673 Alignment = std::max(Alignment,
Align(4));
2679 unsigned AlignInRegs = Alignment.
value() / 4;
2680 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2681 for (
unsigned i = 0; i < Waste; ++i)
2687 unsigned Excess = 4 * (ARM::R4 -
Reg);
2694 if (NSAAOffset != 0 &&
Size > Excess) {
2706 unsigned ByValRegBegin =
Reg;
2707 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2711 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2717 Size = std::max<int>(
Size - Excess, 0);
2725bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2731 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2732 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2733 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2734 const SelectionDAG &DAG = CLI.
DAG;
2739 assert(Subtarget->supportsTailCall());
2752 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2754 if (!(Subtarget->isThumb1Only() ||
2755 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2756 AddressRegisters.
insert(ARM::R12);
2757 for (
const CCValAssign &AL : ArgLocs)
2759 AddressRegisters.
erase(
AL.getLocReg());
2760 if (AddressRegisters.
empty()) {
2761 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2780 <<
" (guaranteed tail-call CC)\n");
2781 return CalleeCC == CallerCC;
2786 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2788 if (isCalleeStructRet != isCallerStructRet) {
2801 const GlobalValue *GV =
G->getGlobal();
2804 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2805 TT.isOSBinFormatMachO())) {
2814 getEffectiveCallingConv(CalleeCC, isVarArg),
2815 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
2822 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2823 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2824 if (CalleeCC != CallerCC) {
2825 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2826 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2835 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2843 const MachineRegisterInfo &MRI = MF.
getRegInfo();
2845 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2864 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2873 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2886 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2889 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2893 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2898 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2920 bool isLittleEndian = Subtarget->isLittle();
2923 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2932 "secure entry function would return value through pointer",
2937 for (
unsigned i = 0, realRVLocIdx = 0;
2939 ++i, ++realRVLocIdx) {
2940 CCValAssign &VA = RVLocs[i];
2943 SDValue Arg = OutVals[realRVLocIdx];
2944 bool ReturnF16 =
false;
2946 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
2979 auto RetVT = Outs[realRVLocIdx].ArgVT;
3001 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3005 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3011 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3023 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3025 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3030 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3040 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3066 !Subtarget->isMClass()) {
3067 if (Subtarget->isThumb1Only())
3074 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3077bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3078 if (
N->getNumValues() != 1)
3080 if (!
N->hasNUsesOfValue(1, 0))
3084 SDNode *
Copy = *
N->user_begin();
3088 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3090 TCChain =
Copy->getOperand(0);
3091 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3092 SDNode *VMov =
Copy;
3094 SmallPtrSet<SDNode*, 2>
Copies;
3095 for (SDNode *U : VMov->
users()) {
3103 for (SDNode *U : VMov->
users()) {
3104 SDValue UseChain =
U->getOperand(0);
3112 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3120 if (!
Copy->hasOneUse())
3127 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3129 TCChain =
Copy->getOperand(0);
3134 bool HasRet =
false;
3135 for (
const SDNode *U :
Copy->users()) {
3136 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3137 U->getOpcode() != ARMISD::INTRET_GLUE)
3149bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3150 if (!Subtarget->supportsTailCall())
3167 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3183 EVT PtrVT =
Op.getValueType();
3193 if (Subtarget->genExecuteOnly()) {
3198 auto GV =
new GlobalVariable(
3204 return LowerGlobalAddress(GA, DAG);
3210 if (Subtarget->isThumb1Only())
3211 CPAlign = std::max(CPAlign,
Align(4));
3217 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3224 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3233 unsigned ARMPCLabelIndex = 0;
3239 if (!IsPositionIndependent) {
3242 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3249 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3253 if (!IsPositionIndependent)
3256 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3284ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3287 "This function expects a Darwin target");
3292 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3298 MVT::i32,
DL, Chain, DescAddr,
3313 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3322 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3328ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3331 "Windows specific TLS lowering");
3355 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3363 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3364 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3370 MachinePointerInfo());
3377 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3390 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3392 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3394 ARMConstantPoolValue *CPV =
3405 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3412 TargetLowering::CallLoweringInfo CLI(DAG);
3417 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3418 return CallResult.first;
3427 const GlobalValue *GV = GA->
getGlobal();
3433 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3437 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3440 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3441 ARMConstantPoolValue *CPV =
3448 PtrVT, dl, Chain,
Offset,
3456 PtrVT, dl, Chain,
Offset,
3461 ARMConstantPoolValue *CPV =
3466 PtrVT, dl, Chain,
Offset,
3482 if (
TT.isOSDarwin())
3483 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3485 if (
TT.isOSWindows())
3486 return LowerGlobalTLSAddressWindows(
Op, DAG);
3489 assert(
TT.isOSBinFormatELF() &&
"Only ELF implemented here");
3495 return LowerToTLSGeneralDynamicModel(GA, DAG);
3498 return LowerToTLSExecModels(GA, DAG, model);
3507 while (!Worklist.
empty()) {
3515 if (!
I ||
I->getParent()->getParent() !=
F)
3544 if (!GVar || !GVar->hasInitializer() ||
3545 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3546 !GVar->hasLocalLinkage())
3551 auto *
Init = GVar->getInitializer();
3553 Init->needsDynamicRelocation())
3565 unsigned RequiredPadding = 4 - (
Size % 4);
3566 bool PaddingPossible =
3567 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3572 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3596 if (RequiredPadding != 4) {
3601 while (RequiredPadding--)
3613 ++NumConstpoolPromoted;
3614 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3619 if (!(GV = GA->getAliaseeObject()))
3622 return V->isConstant();
3631 return LowerGlobalAddressWindows(
Op, DAG);
3633 return LowerGlobalAddressELF(
Op, DAG);
3635 return LowerGlobalAddressDarwin(
Op, DAG);
3647 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3665 }
else if (Subtarget->isROPI() && IsRO) {
3670 }
else if (Subtarget->isRWPI() && !IsRO) {
3673 if (Subtarget->useMovt()) {
3676 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3678 ARMConstantPoolValue *CPV =
3681 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3695 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3696 if (Subtarget->useMovt())
3700 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3704 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3713 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3714 "ROPI/RWPI not currently supported for Darwin");
3719 if (Subtarget->useMovt())
3730 if (Subtarget->isGVIndirectSymbol(GV))
3739 "non-Windows COFF is not supported");
3740 assert(Subtarget->useMovt() &&
3741 "Windows on ARM expects to use movw/movt");
3742 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3743 "ROPI/RWPI not currently supported for Windows");
3750 else if (!TM.shouldAssumeDSOLocal(GV))
3773 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3774 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3775 Op.getOperand(1), Val);
3781 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3788 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3792SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3795 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3799 case Intrinsic::arm_gnu_eabi_mcount: {
3805 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3806 const uint32_t *
Mask =
3808 assert(Mask &&
"Missing call preserved mask for calling convention");
3813 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3817 if (Subtarget->isThumb())
3820 ARM::tBL_PUSHLR, dl, ResultTys,
3821 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3822 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3826 {ReturnAddress, Callee, RegisterMask, Chain}),
3835 unsigned IntNo =
Op.getConstantOperandVal(0);
3839 case Intrinsic::localaddress: {
3841 const auto *RegInfo = Subtarget->getRegisterInfo();
3842 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
3844 Op.getSimpleValueType());
3846 case Intrinsic::eh_recoverfp: {
3852 "llvm.eh.recoverfp must take a function as the first argument");
3853 const auto *RegInfo = Subtarget->getRegisterInfo();
3856 MachineBasicBlock &
MBB = *MF.
begin();
3862 case Intrinsic::thread_pointer: {
3864 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3866 case Intrinsic::arm_cls: {
3870 const SDValue &Operand =
Op.getOperand(1);
3871 const EVT VTy =
Op.getValueType();
3874 case Intrinsic::arm_cls64: {
3880 case Intrinsic::arm_neon_vcls:
3881 case Intrinsic::arm_mve_vcls: {
3884 const EVT VTy =
Op.getValueType();
3887 case Intrinsic::eh_sjlj_lsda: {
3889 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3894 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3895 ARMConstantPoolValue *CPV =
3899 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3904 if (IsPositionIndependent) {
3906 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3910 case Intrinsic::arm_neon_vabs:
3913 case Intrinsic::arm_neon_vabds:
3914 if (
Op.getValueType().isInteger())
3916 Op.getOperand(1),
Op.getOperand(2));
3918 case Intrinsic::arm_neon_vabdu:
3920 Op.getOperand(1),
Op.getOperand(2));
3921 case Intrinsic::arm_neon_vmulls:
3922 case Intrinsic::arm_neon_vmullu: {
3923 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3924 ? ARMISD::VMULLs : ARMISD::VMULLu;
3925 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3926 Op.getOperand(1),
Op.getOperand(2));
3928 case Intrinsic::arm_neon_vminnm:
3929 case Intrinsic::arm_neon_vmaxnm: {
3930 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3932 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3933 Op.getOperand(1),
Op.getOperand(2));
3935 case Intrinsic::arm_neon_vminu:
3936 case Intrinsic::arm_neon_vmaxu: {
3937 if (
Op.getValueType().isFloatingPoint())
3939 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3941 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3942 Op.getOperand(1),
Op.getOperand(2));
3944 case Intrinsic::arm_neon_vmins:
3945 case Intrinsic::arm_neon_vmaxs: {
3947 if (!
Op.getValueType().isFloatingPoint()) {
3948 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3950 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3951 Op.getOperand(1),
Op.getOperand(2));
3953 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3955 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3956 Op.getOperand(1),
Op.getOperand(2));
3958 case Intrinsic::arm_neon_vtbl1:
3959 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
3960 Op.getOperand(1),
Op.getOperand(2));
3961 case Intrinsic::arm_neon_vtbl2:
3962 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
3963 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3964 case Intrinsic::arm_mve_pred_i2v:
3965 case Intrinsic::arm_mve_pred_v2i:
3966 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
3968 case Intrinsic::arm_mve_vreinterpretq:
3969 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
3971 case Intrinsic::arm_mve_lsll:
3972 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
3973 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3974 case Intrinsic::arm_mve_asrl:
3975 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
3976 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3977 case Intrinsic::arm_mve_vsli:
3978 return DAG.
getNode(ARMISD::VSLIIMM, SDLoc(
Op),
Op->getVTList(),
3979 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3980 case Intrinsic::arm_mve_vsri:
3981 return DAG.
getNode(ARMISD::VSRIIMM, SDLoc(
Op),
Op->getVTList(),
3982 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3993 if (!Subtarget->hasDataBarrier()) {
3997 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
3998 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
3999 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
4009 }
else if (Subtarget->preferISHSTBarriers() &&
4018 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4026 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4028 return Op.getOperand(0);
4031 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4033 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4035 return Op.getOperand(0);
4037 unsigned isData =
Op.getConstantOperandVal(4);
4038 if (Subtarget->isThumb()) {
4040 isRead = ~isRead & 1;
4041 isData = ~isData & 1;
4044 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4059 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4067 const SDLoc &dl)
const {
4069 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4071 const TargetRegisterClass *RC;
4073 RC = &ARM::tGPRRegClass;
4075 RC = &ARM::GPRRegClass;
4089 MVT::i32, dl, Root, FIN,
4095 if (!Subtarget->isLittle())
4097 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4110 const Value *OrigArg,
4111 unsigned InRegsParamRecordIdx,
4112 int ArgOffset,
unsigned ArgSize)
const {
4126 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4127 unsigned RBegin, REnd;
4132 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4137 ArgOffset = -4 * (ARM::R4 - RBegin);
4144 const TargetRegisterClass *RC =
4147 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4151 MachinePointerInfo(OrigArg, 4 * i));
4156 if (!MemOps.
empty())
4165 unsigned TotalArgRegsSaveSize,
4166 bool ForceMutable)
const {
4168 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4177 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4181bool ARMTargetLowering::splitValueIntoRegisterParts(
4183 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4185 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4197SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4199 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4200 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4213SDValue ARMTargetLowering::LowerFormalArguments(
4220 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4229 unsigned CurArgIdx = 0;
4241 unsigned ArgRegBegin = ARM::R4;
4242 for (
const CCValAssign &VA : ArgLocs) {
4248 if (!
Flags.isByVal())
4252 unsigned RBegin, REnd;
4254 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4260 int lastInsIndex = -1;
4264 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4267 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4271 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4272 CCValAssign &VA = ArgLocs[i];
4273 if (Ins[VA.
getValNo()].isOrigArg()) {
4274 std::advance(CurOrigArg,
4275 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4276 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4287 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4294 MVT::f64, dl, Chain, FIN,
4297 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4305 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4307 const TargetRegisterClass *RC;
4309 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4310 RC = &ARM::HPRRegClass;
4311 else if (RegVT == MVT::f32)
4312 RC = &ARM::SPRRegClass;
4313 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4314 RegVT == MVT::v4bf16)
4315 RC = &ARM::DPRRegClass;
4316 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4317 RegVT == MVT::v8bf16)
4318 RC = &ARM::QPRRegClass;
4319 else if (RegVT == MVT::i32)
4321 : &ARM::GPRRegClass;
4358 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4367 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4373 if (index != lastInsIndex)
4375 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4381 if (
Flags.isByVal()) {
4382 assert(Ins[index].isOrigArg() &&
4383 "Byval arguments cannot be implicit");
4387 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4421 lastInsIndex = index;
4428 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4429 TotalArgRegsSaveSize);
4433 "secure entry function must not be variadic", dl.
getDebugLoc()));
4443 assert(StackAlign &&
"data layout string is missing stack alignment");
4444 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4453 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4462 return CFP->getValueAPF().isPosZero();
4465 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4466 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4469 return CFP->getValueAPF().isPosZero();
4472 Op->getValueType(0) == MVT::f64) {
4476 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4485 if (
Op->getFlags().hasNoSignedWrap())
4501 (isIntEqualitySetCC(CC) ||
4510 const SDLoc &dl)
const {
4512 unsigned C = RHSC->getZExtValue();
4576 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4580 unsigned Mask =
LHS.getConstantOperandVal(1);
4582 uint64_t RHSV = RHSC->getZExtValue();
4583 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4585 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4599 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4602 LHS.getConstantOperandVal(1) < 31) {
4603 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4628 unsigned CompareType;
4631 CompareType = ARMISD::CMP;
4636 CompareType = ARMISD::CMPZ;
4645 if (CompareType != ARMISD::CMPZ &&
isCMN(
RHS, CC, DAG)) {
4646 CompareType = ARMISD::CMN;
4648 }
else if (CompareType != ARMISD::CMPZ &&
isCMN(
LHS, CC, DAG)) {
4649 CompareType = ARMISD::CMN;
4661 bool Signaling)
const {
4662 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4668 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4677std::pair<SDValue, SDValue>
4680 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4692 switch (
Op.getOpcode()) {
4744 return std::make_pair(
Value, OverflowCmp);
4757 return Cmp.getValue(1);
4785 return DAG.
getNode(ARMISD::CMOV,
DL, VT, Zero, One, ARMcc, Flags);
4797 EVT VT =
Op.getValueType();
4798 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4801 switch (
Op.getOpcode()) {
4815 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4821 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4824 ARMcc, OverflowCmp);
4834 EVT VT =
Op.getValueType();
4835 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4845 switch (
Op->getOpcode()) {
4847 NewOpcode = ARMISD::UQADD8b;
4850 NewOpcode = ARMISD::QADD8b;
4853 NewOpcode = ARMISD::UQSUB8b;
4856 NewOpcode = ARMISD::QSUB8b;
4861 switch (
Op->getOpcode()) {
4863 NewOpcode = ARMISD::UQADD16b;
4866 NewOpcode = ARMISD::QADD16b;
4869 NewOpcode = ARMISD::UQSUB16b;
4872 NewOpcode = ARMISD::QSUB16b;
4880 DAG.
getNode(NewOpcode, dl, MVT::i32,
4891 unsigned Opc =
Cond.getOpcode();
4893 if (
Cond.getResNo() == 1 &&
4901 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4902 EVT VT =
Op.getValueType();
4904 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4912 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4913 const ConstantSDNode *CMOVTrue =
4915 const ConstantSDNode *CMOVFalse =
4918 if (CMOVTrue && CMOVFalse) {
4924 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
4926 False = SelectFalse;
4927 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
4933 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
4934 Cond.getOperand(3), DAG);
4944 bool &swpCmpOps,
bool &swpVselOps) {
4972 swpCmpOps = !swpCmpOps;
4973 swpVselOps = !swpVselOps;
4996 if (!Subtarget->hasFP64() && VT == MVT::f64) {
4998 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5000 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5014 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5035 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5037 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5058 EVT VT =
Op.getValueType();
5080 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5093 int64_t PosVal = std::max(Val1, Val2);
5094 int64_t NegVal = std::min(Val1, Val2);
5106 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5109 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5141 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5146 if (*K != KTmp || V != VTmp)
5157bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5159 return !Subtarget->hasVFP2Base();
5161 return !Subtarget->hasFP64();
5163 return !Subtarget->hasFullFP16();
5171 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5179 if (TVal == ~FVal) {
5180 Opcode = ARMISD::CSINV;
5181 }
else if (TVal == ~FVal + 1) {
5182 Opcode = ARMISD::CSNEG;
5183 }
else if (TVal + 1 == FVal) {
5184 Opcode = ARMISD::CSINC;
5185 }
else if (TVal == FVal + 1) {
5186 Opcode = ARMISD::CSINC;
5189 InvertCond = !InvertCond;
5196 if (Opcode != ARMISD::CSINC &&
5200 InvertCond = !InvertCond;
5206 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5209 InvertCond = !InvertCond;
5216 EVT VT =
Op.getValueType();
5220 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5232 if (VT == MVT::i32 &&
5251 if (
Op.getValueType().isInteger()) {
5259 LHS.getValueType() ==
RHS.getValueType()) {
5260 EVT VT =
LHS.getValueType();
5266 Shift = DAG.
getNOT(dl, Shift, VT);
5278 if (
LHS.getValueType() == MVT::i32) {
5282 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5288 EVT VT =
Op.getValueType();
5289 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5293 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5298 if (!
RHS.getNode()) {
5304 if (
LHS.getValueType() == MVT::i32) {
5315 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5316 TrueVal.getValueType() == MVT::f32 ||
5317 TrueVal.getValueType() == MVT::f64)) {
5331 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5341 if (Subtarget->hasFPARMv8Base() &&
5343 (
TrueVal.getValueType() == MVT::f16 ||
5344 TrueVal.getValueType() == MVT::f32 ||
5345 TrueVal.getValueType() == MVT::f64)) {
5346 bool swpCmpOps =
false;
5347 bool swpVselOps =
false;
5361 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5364 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5374 if (!
N->hasOneUse())
5377 if (!
N->getNumValues())
5379 EVT VT =
Op.getValueType();
5380 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5397 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5398 Ld->getPointerInfo(), Ld->getAlign(),
5399 Ld->getMemOperand()->getFlags());
5415 SDValue Ptr = Ld->getBasePtr();
5417 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5418 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5423 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5424 Ld->getPointerInfo().getWithOffset(4),
5426 Ld->getMemOperand()->getFlags());
5444 bool LHSSeenZero =
false;
5446 bool RHSSeenZero =
false;
5448 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5459 if (
LHS.getValueType() == MVT::f32) {
5465 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5477 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5478 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5493 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5512 unsigned Opc =
Cond.getOpcode();
5514 !Subtarget->isThumb1Only();
5515 if (
Cond.getResNo() == 1 &&
5525 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5530 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5545 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5550 if (!
RHS.getNode()) {
5558 unsigned Opc =
LHS.getOpcode();
5560 !Subtarget->isThumb1Only();
5572 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5579 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5583 if (
LHS.getValueType() == MVT::i32) {
5586 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5589 SDNodeFlags
Flags =
Op->getFlags();
5590 if (
Flags.hasNoNaNs() &&
5595 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5609 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5623 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5626 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5631 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5632 Addr,
Op.getOperand(2), JTI);
5636 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5640 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5643 DAG.
getLoad(PTy, dl, Chain, Addr,
5646 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5651 EVT VT =
Op.getValueType();
5654 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5655 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5663 const EVT OpTy =
Op.getOperand(0).getValueType();
5664 if (OpTy == MVT::v4f32)
5666 else if (OpTy == MVT::v4f16 && HasFullFP16)
5668 else if (OpTy == MVT::v8f16 && HasFullFP16)
5673 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5676 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5681 EVT VT =
Op.getValueType();
5685 bool IsStrict =
Op->isStrictFPOpcode();
5686 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5688 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5701 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5702 CallOptions, Loc, Chain);
5712 Loc,
Op.getValueType(), SrcVal);
5721 EVT VT =
Op.getValueType();
5723 EVT FromVT =
Op.getOperand(0).getValueType();
5725 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5727 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5728 Subtarget->hasFP64())
5730 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5731 Subtarget->hasFullFP16())
5733 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5734 Subtarget->hasMVEFloatOps())
5736 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5737 Subtarget->hasMVEFloatOps())
5740 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5757 EVT VT =
Op.getValueType();
5760 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5766 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5767 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5768 "Invalid type for custom lowering!");
5773 if (VT == MVT::v4f32)
5774 DestVecType = MVT::v4i32;
5775 else if (VT == MVT::v4f16 && HasFullFP16)
5776 DestVecType = MVT::v4i16;
5777 else if (VT == MVT::v8f16 && HasFullFP16)
5778 DestVecType = MVT::v8i16;
5784 switch (
Op.getOpcode()) {
5796 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5801 EVT VT =
Op.getValueType();
5804 if (isUnsupportedFloatingType(VT)) {
5814 CallOptions, SDLoc(
Op)).first;
5825 EVT VT =
Op.getValueType();
5829 bool UseNEON = !InGPR && Subtarget->hasNEON();
5836 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5843 if (SrcVT == MVT::f32) {
5846 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5849 }
else if (VT == MVT::f32)
5850 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5865 if (VT == MVT::f32) {
5877 if (SrcVT == MVT::f64)
5886 if (VT == MVT::f32) {
5899 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5907 EVT VT =
Op.getValueType();
5909 unsigned Depth =
Op.getConstantOperandVal(0);
5911 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5915 MachinePointerInfo());
5924 const ARMBaseRegisterInfo &ARI =
5925 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
5930 EVT VT =
Op.getValueType();
5932 unsigned Depth =
Op.getConstantOperandVal(0);
5937 MachinePointerInfo());
5945 return StringSwitch<Register>(
RegName)
5946 .Case(
"sp", ARM::SP)
5957 assert(
N->getValueType(0) == MVT::i64
5958 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
5961 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6001 const APInt &APIntIndex = Index->getAPIntValue();
6003 NewIndex *= APIntIndex;
6032 EVT SrcVT =
Op.getValueType();
6033 EVT DstVT =
N->getValueType(0);
6035 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6036 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6037 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6040 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6041 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6042 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6049 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6061 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6069 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6071 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6073 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6093 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6102 EVT VT =
Op.getValueType();
6124 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6134 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6145 EVT VT =
Op.getValueType();
6166 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6187 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6239 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6267 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6297 EVT VT =
N->getValueType(0);
6298 if (VT.
isVector() && ST->hasNEON()) {
6307 if (ElemTy == MVT::i8) {
6315 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6318 unsigned NumBits = ElemTy.getSizeInBits();
6320 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6330 if (ElemTy == MVT::i64) {
6343 if (!ST->hasV6T2Ops())
6352 EVT VT =
N->getValueType(0);
6355 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6356 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6357 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6358 "Unexpected type for custom ctpop lowering");
6366 unsigned EltSize = 8;
6389 Op =
Op.getOperand(0);
6391 APInt SplatBits, SplatUndef;
6392 unsigned SplatBitSize;
6395 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6397 SplatBitSize > ElementBits)
6408 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6412 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6423 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6428 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6429 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6438 EVT VT =
N->getValueType(0);
6453 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6455 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6460 "unexpected vector shift opcode");
6462 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6463 unsigned VShiftOpc =
6464 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6465 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6471 EVT ShiftVT =
N->getOperand(1).getValueType();
6474 unsigned VShiftOpc =
6475 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6476 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6481 EVT VT =
N->getValueType(0);
6490 "Unknown shift to lower!");
6492 unsigned ShOpc =
N->getOpcode();
6493 if (ST->hasMVEIntegerOps()) {
6495 unsigned ShPartsOpc = ARMISD::LSLL;
6516 ShPartsOpc = ARMISD::LSRL;
6518 ShPartsOpc = ARMISD::ASRL;
6523 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6537 if (ST->isThumb1Only())
6542 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6546 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6550 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6558 bool Invert =
false;
6565 EVT VT =
Op.getValueType();
6573 assert(ST->hasMVEIntegerOps() &&
6574 "No hardware support for integer vector comparison!");
6576 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6597 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6601 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6611 switch (SetCCOpcode) {
6615 if (ST->hasMVEFloatOps()) {
6618 Invert =
true; [[fallthrough]];
6623 case ISD::SETLT: Swap =
true; [[fallthrough]];
6627 case ISD::SETLE: Swap =
true; [[fallthrough]];
6643 Result = DAG.
getNOT(dl, Result, VT);
6646 case ISD::SETUO: Invert =
true; [[fallthrough]];
6655 Result = DAG.
getNOT(dl, Result, VT);
6661 switch (SetCCOpcode) {
6664 if (ST->hasMVEIntegerOps()) {
6667 Invert =
true; [[fallthrough]];
6670 case ISD::SETLT: Swap =
true; [[fallthrough]];
6672 case ISD::SETLE: Swap =
true; [[fallthrough]];
6689 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6692 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6697 Result = DAG.
getNOT(dl, Result, VT);
6722 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6725 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6731 Result = DAG.
getNOT(dl, Result, VT);
6740 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6757 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6768 unsigned OpCmode, Imm;
6779 switch (SplatBitSize) {
6784 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6787 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6792 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6793 if ((SplatBits & ~0xff) == 0) {
6799 if ((SplatBits & ~0xff00) == 0) {
6802 Imm = SplatBits >> 8;
6812 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6813 if ((SplatBits & ~0xff) == 0) {
6819 if ((SplatBits & ~0xff00) == 0) {
6822 Imm = SplatBits >> 8;
6825 if ((SplatBits & ~0xff0000) == 0) {
6828 Imm = SplatBits >> 16;
6831 if ((SplatBits & ~0xff000000) == 0) {
6834 Imm = SplatBits >> 24;
6841 if ((SplatBits & ~0xffff) == 0 &&
6842 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6845 Imm = SplatBits >> 8;
6853 if ((SplatBits & ~0xffffff) == 0 &&
6854 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6857 Imm = SplatBits >> 16;
6873 unsigned ImmMask = 1;
6875 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6876 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6878 }
else if ((SplatBits & BitMask) != 0) {
6887 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6901 EVT VT =
Op.getValueType();
6902 bool IsDouble = (VT == MVT::f64);
6908 if (
ST->genExecuteOnly()) {
6910 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6911 "Unexpected architecture");
6929 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
6934 if (!
ST->hasVFP3Base())
6939 if (IsDouble && !Subtarget->hasFP64())
6946 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
6964 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
6973 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7027 unsigned ExpectedElt = Imm;
7028 for (
unsigned i = 1; i < NumElts; ++i) {
7032 if (ExpectedElt == NumElts)
7035 if (M[i] < 0)
continue;
7036 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7044 bool &ReverseVEXT,
unsigned &Imm) {
7046 ReverseVEXT =
false;
7057 unsigned ExpectedElt = Imm;
7058 for (
unsigned i = 1; i < NumElts; ++i) {
7062 if (ExpectedElt == NumElts * 2) {
7067 if (M[i] < 0)
continue;
7068 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7083 return VT == MVT::v8i8 && M.size() == 8;
7088 if (Mask.size() == Elements * 2)
7089 return Index / Elements;
7090 return Mask[Index] == 0 ? 0 : 1;
7120 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7128 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7130 for (
unsigned j = 0; j < NumElts; j += 2) {
7131 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7132 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7137 if (M.size() == NumElts*2)
7152 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7155 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7157 for (
unsigned j = 0; j < NumElts; j += 2) {
7158 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7159 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7164 if (M.size() == NumElts*2)
7184 if (M.size() != NumElts && M.size() != NumElts*2)
7187 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7189 for (
unsigned j = 0; j < NumElts; ++j) {
7190 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7195 if (M.size() == NumElts*2)
7214 if (M.size() != NumElts && M.size() != NumElts*2)
7217 unsigned Half = NumElts / 2;
7218 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7220 for (
unsigned j = 0; j < NumElts; j += Half) {
7221 unsigned Idx = WhichResult;
7222 for (
unsigned k = 0; k < Half; ++k) {
7223 int MIdx = M[i + j + k];
7224 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7231 if (M.size() == NumElts*2)
7255 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7258 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7260 unsigned Idx = WhichResult * NumElts / 2;
7261 for (
unsigned j = 0; j < NumElts; j += 2) {
7262 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7263 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7269 if (M.size() == NumElts*2)
7288 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7291 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7293 unsigned Idx = WhichResult * NumElts / 2;
7294 for (
unsigned j = 0; j < NumElts; j += 2) {
7295 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7296 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7302 if (M.size() == NumElts*2)
7315 unsigned &WhichResult,
7318 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7319 return ARMISD::VTRN;
7320 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7321 return ARMISD::VUZP;
7322 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7323 return ARMISD::VZIP;
7327 return ARMISD::VTRN;
7329 return ARMISD::VUZP;
7331 return ARMISD::VZIP;
7340 if (NumElts != M.size())
7344 for (
unsigned i = 0; i != NumElts; ++i)
7345 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7354 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7362 int Ofs = Top ? 1 : 0;
7363 int Upper = SingleSource ? 0 : NumElts;
7364 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7365 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7367 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7376 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7385 unsigned Offset = Top ? 0 : 1;
7386 unsigned N = SingleSource ? 0 : NumElts;
7387 for (
unsigned i = 0; i < NumElts; i += 2) {
7388 if (M[i] >= 0 && M[i] != (
int)i)
7390 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7399 if (NumElts != M.size())
7407 unsigned Off0 = rev ? NumElts / 2 : 0;
7408 unsigned Off1 = rev ? 0 : NumElts / 2;
7409 for (
unsigned i = 0; i < NumElts; i += 2) {
7410 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7412 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7428 if (!ST->hasMVEFloatOps())
7433 if (VT != MVT::v8f16)
7454 for (
unsigned i = 1; i < 4; i++) {
7469 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7481 if (!ST->hasMVEFloatOps())
7486 if (VT != MVT::v4f32)
7502 for (
unsigned i = 1; i < 4; i++) {
7513 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7525 Val =
N->getAsZExtVal();
7527 if (ST->isThumb1Only()) {
7528 if (Val <= 255 || ~Val <= 255)
7540 EVT VT =
Op.getValueType();
7542 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7546 unsigned BitsPerBool;
7550 }
else if (NumElts == 4) {
7553 }
else if (NumElts == 8) {
7556 }
else if (NumElts == 16) {
7567 return U.get().isUndef() || U.get() == FirstOp;
7571 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7575 unsigned Bits32 = 0;
7576 for (
unsigned i = 0; i < NumElts; ++i) {
7580 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7582 Bits32 |= BoolMask << (i * BitsPerBool);
7588 for (
unsigned i = 0; i < NumElts; ++i) {
7601 if (!ST->hasMVEIntegerOps())
7605 EVT VT =
Op.getValueType();
7615 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7619 for (
unsigned I = 2;
I < NumElts;
I++) {
7635 switch (
N->getOpcode()) {
7646 return N->getOperand(1).getNode() ==
Op;
7648 switch (
N->getConstantOperandVal(0)) {
7649 case Intrinsic::arm_mve_add_predicated:
7650 case Intrinsic::arm_mve_mul_predicated:
7651 case Intrinsic::arm_mve_qadd_predicated:
7652 case Intrinsic::arm_mve_vhadd:
7653 case Intrinsic::arm_mve_hadd_predicated:
7654 case Intrinsic::arm_mve_vqdmulh:
7655 case Intrinsic::arm_mve_qdmulh_predicated:
7656 case Intrinsic::arm_mve_vqrdmulh:
7657 case Intrinsic::arm_mve_qrdmulh_predicated:
7658 case Intrinsic::arm_mve_vqdmull:
7659 case Intrinsic::arm_mve_vqdmull_predicated:
7661 case Intrinsic::arm_mve_sub_predicated:
7662 case Intrinsic::arm_mve_qsub_predicated:
7663 case Intrinsic::arm_mve_vhsub:
7664 case Intrinsic::arm_mve_hsub_predicated:
7665 return N->getOperand(2).getNode() ==
Op;
7680 EVT VT =
Op.getValueType();
7688 APInt SplatBits, SplatUndef;
7689 unsigned SplatBitSize;
7691 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7698 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7700 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7701 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7702 : SplatBitSize == 16 ? MVT::v8i16
7706 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7709 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7710 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7715 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7719 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7723 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7725 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7729 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7733 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7737 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7743 if (
ST->hasMVEIntegerOps() &&
7744 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7745 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7746 : SplatBitSize == 16 ? MVT::v8i16
7750 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7763 bool isOnlyLowElement =
true;
7764 bool usesOnlyOneValue =
true;
7765 bool hasDominantValue =
false;
7770 DenseMap<SDValue, unsigned> ValueCounts;
7772 for (
unsigned i = 0; i < NumElts; ++i) {
7777 isOnlyLowElement =
false;
7781 unsigned &
Count = ValueCounts[
V];
7784 if (++
Count > (NumElts / 2)) {
7785 hasDominantValue =
true;
7789 if (ValueCounts.
size() != 1)
7790 usesOnlyOneValue =
false;
7791 if (!
Value.getNode() && !ValueCounts.
empty())
7794 if (ValueCounts.
empty())
7800 (VT != MVT::v8f16 ||
ST->hasFullFP16()))
7807 if (hasDominantValue && EltSize <= 32) {
7816 ConstantSDNode *constIndex;
7823 if (VT !=
Value->getOperand(0).getValueType()) {
7826 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7831 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7836 if (!usesOnlyOneValue) {
7839 for (
unsigned I = 0;
I < NumElts; ++
I) {
7844 Ops.push_back(
Op.getOperand(
I));
7854 assert(FVT == MVT::f32 || FVT == MVT::f16);
7855 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7856 for (
unsigned i = 0; i < NumElts; ++i)
7861 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7865 if (usesOnlyOneValue) {
7868 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7892 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7912 if (EltSize >= 32) {
7918 for (
unsigned i = 0; i < NumElts; ++i)
7931 (VT == MVT::v8f16 && !
ST->hasFullFP16())) {
7933 for (
unsigned i = 0 ; i < NumElts; ++i) {
7952 EVT VT =
Op.getValueType();
7955 struct ShuffleSourceInfo {
7957 unsigned MinElt = std::numeric_limits<unsigned>::max();
7958 unsigned MaxElt = 0;
7968 int WindowScale = 1;
7970 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7978 for (
unsigned i = 0; i < NumElts; ++i) {
7993 SDValue SourceVec =
V.getOperand(0);
7995 if (Source == Sources.
end())
7999 unsigned EltNo =
V.getConstantOperandVal(1);
8006 if (Sources.
size() > 2)
8012 for (
auto &Source : Sources) {
8013 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8014 if (SrcEltTy.
bitsLT(SmallestEltTy))
8015 SmallestEltTy = SrcEltTy;
8017 unsigned ResMultiplier =
8025 for (
auto &Src : Sources) {
8026 EVT SrcVT = Src.ShuffleVec.getValueType();
8030 if (SrcVTSize == VTSize)
8039 if (SrcVTSize < VTSize) {
8040 if (2 * SrcVTSize != VTSize)
8046 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8050 if (SrcVTSize != 2 * VTSize)
8053 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8058 if (Src.MinElt >= NumSrcElts) {
8063 Src.WindowBase = -NumSrcElts;
8064 }
else if (Src.MaxElt < NumSrcElts) {
8078 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8081 Src.WindowBase = -Src.MinElt;
8088 for (
auto &Src : Sources) {
8089 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8090 if (SrcEltTy == SmallestEltTy)
8093 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8095 Src.WindowBase *= Src.WindowScale;
8100 for (
auto Src : Sources)
8101 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8109 if (
Entry.isUndef())
8118 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8121 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8125 int *LaneMask = &
Mask[i * ResMultiplier];
8127 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8128 ExtractBase += NumElts * (Src - Sources.begin());
8129 for (
int j = 0;
j < LanesDefined; ++
j)
8130 LaneMask[j] = ExtractBase + j;
8136 assert(Sources.size() <= 2 &&
"Too many sources!");
8139 for (
unsigned i = 0; i < Sources.size(); ++i)
8146 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8168 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8188 unsigned PFIndexes[4];
8189 for (
unsigned i = 0; i != 4; ++i) {
8193 PFIndexes[i] = M[i];
8197 unsigned PFTableIndex =
8198 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8200 unsigned Cost = (PFEntry >> 30);
8206 bool ReverseVEXT, isV_UNDEF;
8207 unsigned Imm, WhichResult;
8210 if (EltSize >= 32 ||
8217 else if (Subtarget->hasNEON() &&
8222 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8225 else if (Subtarget->hasMVEIntegerOps() &&
8229 else if (Subtarget->hasMVEIntegerOps() &&
8243 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8244 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8245 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8248 if (LHSID == (1*9+2)*9+3)
return LHS;
8249 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8263 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8266 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8269 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8274 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8279 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8306 for (
int I : ShuffleMask)
8310 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8,
V1,
8313 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8,
V1, V2,
8319 EVT VT =
Op.getValueType();
8321 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8322 "Expect an v8i16/v16i8 type");
8328 std::vector<int> NewMask;
8332 NewMask.push_back(i);
8362 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8372 if (VT != MVT::v16i1)
8373 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8388 EVT VT =
Op.getValueType();
8392 assert(ST->hasMVEIntegerOps() &&
8393 "No support for vector shuffle of boolean predicates");
8403 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8419 "Expected identical vector type in expanded i1 shuffle!");
8423 PredAsVector2, ShuffleMask);
8428 if (VT == MVT::v2i1) {
8429 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8432 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8434 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8445 EVT VT =
Op.getValueType();
8449 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8450 "Unexpected vector type");
8452 int QuarterSize = NumElts / 4;
8461 for (
int i = 0; i <
Length; i++) {
8462 if (ShuffleMask[Start + i] >= 0) {
8463 if (ShuffleMask[Start + i] %
Length != i)
8465 MovIdx = ShuffleMask[Start + i] /
Length;
8473 for (
int i = 1; i <
Length; i++) {
8474 if (ShuffleMask[Start + i] >= 0 &&
8475 (ShuffleMask[Start + i] /
Length != MovIdx ||
8476 ShuffleMask[Start + i] %
Length != i))
8482 for (
int Part = 0; Part < 4; ++Part) {
8484 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8498 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8503 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8505 for (
int Part = 0; Part < 4; ++Part)
8506 for (
int i = 0; i < QuarterSize; i++)
8508 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8510 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8513 for (
int Part = 0; Part < 4; ++Part)
8529 EVT VT =
Op.getValueType();
8541 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8545 if (Mask[i] != i + BaseOffset) {
8546 if (OffElement == -1)
8552 return NonUndef > 2 && OffElement != -1;
8556 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8558 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8569 ShuffleMask[OffElement] < (
int)NumElts ?
V1 : V2,
8580 EVT VT =
Op.getValueType();
8584 if (ST->hasMVEIntegerOps() && EltSize == 1)
8595 if (EltSize <= 32) {
8599 if (Lane == -1) Lane = 0;
8603 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8610 bool IsScalarToVector =
true;
8611 for (
unsigned i = 1, e =
V1.getNumOperands(); i != e; ++i)
8612 if (!
V1.getOperand(i).isUndef()) {
8613 IsScalarToVector =
false;
8616 if (IsScalarToVector)
8617 return DAG.
getNode(ARMISD::VDUP, dl, VT,
V1.getOperand(0));
8619 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
V1,
8623 bool ReverseVEXT =
false;
8625 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8628 return DAG.
getNode(ARMISD::VEXT, dl, VT,
V1, V2,
8633 return DAG.
getNode(ARMISD::VREV64, dl, VT,
V1);
8635 return DAG.
getNode(ARMISD::VREV32, dl, VT,
V1);
8637 return DAG.
getNode(ARMISD::VREV16, dl, VT,
V1);
8649 unsigned WhichResult = 0;
8650 bool isV_UNDEF =
false;
8651 if (ST->hasNEON()) {
8653 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8660 if (ST->hasMVEIntegerOps()) {
8662 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2,
V1,
8665 return DAG.
getNode(ARMISD::VMOVN, dl, VT,
V1, V2,
8695 }) &&
"Unexpected shuffle index into UNDEF operand!");
8698 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8701 assert((WhichResult == 0) &&
8702 "In-place shuffle of concat can only have one result!");
8711 if (ST->hasMVEIntegerOps() && EltSize <= 32 &&
8712 (ST->hasFullFP16() || VT != MVT::v8f16)) {
8716 for (
bool Top : {
false,
true}) {
8717 for (
bool SingleSource : {
false,
true}) {
8718 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8723 SingleSource ?
V1 : V2);
8739 unsigned PFIndexes[4];
8740 for (
unsigned i = 0; i != 4; ++i) {
8741 if (ShuffleMask[i] < 0)
8744 PFIndexes[i] = ShuffleMask[i];
8748 unsigned PFTableIndex =
8749 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8751 unsigned Cost = (PFEntry >> 30);
8757 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8758 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8768 if (EltSize >= 32) {
8776 for (
unsigned i = 0; i < NumElts; ++i) {
8777 if (ShuffleMask[i] < 0)
8781 ShuffleMask[i] < (
int)NumElts ?
V1 : V2,
8789 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8793 if (ST->hasNEON() && VT == MVT::v8i8)
8797 if (ST->hasMVEIntegerOps())
8802 if (VT == MVT::v8f16 && !ST->hasFullFP16()) {
8804 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(0));
8806 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v8i16,
Op.getOperand(1));
8808 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuf);
8816 EVT VecVT =
Op.getOperand(0).getValueType();
8819 assert(ST->hasMVEIntegerOps() &&
8820 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8823 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8824 unsigned Lane =
Op.getConstantOperandVal(2);
8825 unsigned LaneWidth =
8827 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8832 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8845 if (Subtarget->hasMVEIntegerOps() &&
8846 Op.getValueType().getScalarSizeInBits() == 1)
8870 IVecIn, IElt, Lane);
8879 EVT VecVT =
Op.getOperand(0).getValueType();
8882 assert(ST->hasMVEIntegerOps() &&
8883 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8886 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8887 unsigned Lane =
Op.getConstantOperandVal(1);
8888 unsigned LaneWidth =
8910 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8919 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8920 "Unexpected custom CONCAT_VECTORS lowering");
8922 "Unexpected custom CONCAT_VECTORS lowering");
8923 assert(ST->hasMVEIntegerOps() &&
8924 "CONCAT_VECTORS lowering only supported for MVE");
8927 EVT Op1VT =
V1.getValueType();
8928 EVT Op2VT = V2.getValueType();
8929 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8930 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8931 "Unexpected i1 concat operations!");
8944 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8949 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8958 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8959 EVT NewVT = NewV.getValueType();
8960 EVT ConcatVT = ConVec.getValueType();
8961 unsigned ExtScale = 1;
8962 if (NewVT == MVT::v2f64) {
8963 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8976 ConVec = ExtractInto(NewV1, ConVec, j);
8977 ConVec = ExtractInto(NewV2, ConVec, j);
8981 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8987 while (ConcatOps.
size() > 1) {
8988 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8991 ConcatOps[
I / 2] = ConcatPair(
V1, V2);
8995 return ConcatOps[0];
9000 EVT VT =
Op->getValueType(0);
9006 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
9007 "unexpected CONCAT_VECTORS");
9028 EVT VT =
Op.getValueType();
9029 EVT Op1VT =
V1.getValueType();
9034 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9035 assert(ST->hasMVEIntegerOps() &&
9036 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9046 EVT SubVT = MVT::v4i32;
9048 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9058 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
9063 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9072 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9079 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9080 EVT VT =
N->getValueType(0);
9081 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9082 "Expected a vector i1 type!");
9084 EVT FromVT =
Op.getValueType();
9095 if (!Subtarget->hasMVEIntegerOps())
9098 EVT ToVT =
N->getValueType(0);
9141 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9143 EVT FromVT =
N->getOperand(0).getValueType();
9144 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9155 if (!Subtarget->hasMVEIntegerOps())
9160 EVT ToVT =
N->getValueType(0);
9161 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9164 EVT FromVT =
Op.getValueType();
9165 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9179 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9180 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9192 EVT VT =
N->getValueType(0);
9194 SDNode *BVN =
N->getOperand(0).getNode();
9199 unsigned HiElt = 1 - LoElt;
9204 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9220 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9221 SDNode *Elt =
N->getOperand(i).getNode();
9224 unsigned HalfSize = EltSize / 2;
9226 if (!
isIntN(HalfSize,
C->getSExtValue()))
9229 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9268 switch (OrigSimpleTy) {
9284 unsigned ExtOpcode) {
9307 if (ExtendedTy == LD->getMemoryVT())
9308 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9309 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9310 LD->getMemOperand()->getFlags());
9316 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9317 LD->getMemoryVT(), LD->getAlign(),
9318 LD->getMemOperand()->getFlags());
9331 N->getOperand(0)->getValueType(0),
9337 "Expected extending load");
9343 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9352 SDNode *BVN =
N->getOperand(0).getNode();
9354 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9362 EVT VT =
N->getValueType(0);
9368 for (
unsigned i = 0; i != NumElts; ++i) {
9369 const APInt &CInt =
N->getConstantOperandAPInt(i);
9378 unsigned Opcode =
N->getOpcode();
9380 SDNode *N0 =
N->getOperand(0).getNode();
9381 SDNode *N1 =
N->getOperand(1).getNode();
9389 unsigned Opcode =
N->getOpcode();
9391 SDNode *N0 =
N->getOperand(0).getNode();
9392 SDNode *N1 =
N->getOperand(1).getNode();
9402 EVT VT =
Op.getValueType();
9404 "unexpected type for custom-lowering ISD::MUL");
9405 SDNode *N0 =
Op.getOperand(0).getNode();
9406 SDNode *N1 =
Op.getOperand(1).getNode();
9407 unsigned NewOpc = 0;
9411 if (isN0SExt && isN1SExt)
9412 NewOpc = ARMISD::VMULLs;
9416 if (isN0ZExt && isN1ZExt)
9417 NewOpc = ARMISD::VMULLu;
9418 else if (isN1SExt || isN1ZExt) {
9422 NewOpc = ARMISD::VMULLs;
9425 NewOpc = ARMISD::VMULLu;
9429 NewOpc = ARMISD::VMULLu;
9435 if (VT == MVT::v2i64)
9452 "unexpected types for extended operands to VMULL");
9453 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9488 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9522 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9525 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9546 EVT VT =
Op.getValueType();
9547 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9548 "unexpected type for custom-lowering ISD::SDIV");
9555 if (VT == MVT::v8i8) {
9583 EVT VT =
Op.getValueType();
9584 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9585 "unexpected type for custom-lowering ISD::UDIV");
9592 if (VT == MVT::v8i8) {
9631 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9634 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9638 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9658 unsigned Opcode,
bool IsSigned) {
9659 EVT VT0 =
Op.getValue(0).getValueType();
9660 EVT VT1 =
Op.getValue(1).getValueType();
9662 bool InvertCarry = Opcode == ARMISD::SUBE;
9682 EVT VT =
Op.getValueType();
9683 assert((VT == MVT::i32 || VT == MVT::i64) &&
9684 "unexpected type for custom lowering DIV");
9690 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9692 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9699 for (
auto AI : {1, 0}) {
9701 Args.emplace_back(Operand,
9718ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9726 const bool MinSize =
ST.hasMinSize();
9727 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9728 :
ST.hasDivideInARMMode();
9732 if (
N->getOperand(0).getValueType().isVector())
9737 if (!(MinSize && HasDivide))
9750 if (Divisor.
sgt(128))
9758 assert(
Op.getValueType() == MVT::i32 &&
9759 "unexpected type for custom lowering DIV");
9762 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9765 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9771 if (
N->getValueType(0) == MVT::i32)
9772 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9775 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9779void ARMTargetLowering::ExpandDIV_Windows(
9784 assert(
Op.getValueType() == MVT::i64 &&
9785 "unexpected type for custom lowering DIV");
9800std::pair<SDValue, SDValue>
9801ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9807 EVT MemVT =
LD->getMemoryVT();
9808 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9812 unsigned AS =
LD->getAddressSpace();
9813 Align Alignment =
LD->getAlign();
9815 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9818 Alignment <= llvm::Align(2)) {
9821 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9827 Opts, dl,
LD->getChain());
9852 EVT MemVT =
ST->getMemoryVT();
9853 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9857 unsigned AS =
ST->getAddressSpace();
9858 Align Alignment =
ST->getAlign();
9860 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9863 Alignment <= llvm::Align(2)) {
9869 if (
ST->isTruncatingStore())
9873 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9877 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9878 dl,
ST->getChain());
9880 return CallResult.second;
9891 EVT MemVT = LD->getMemoryVT();
9892 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9893 MemVT == MVT::v16i1) &&
9894 "Expected a predicate type!");
9895 assert(MemVT ==
Op.getValueType());
9897 "Expected a non-extending load");
9898 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9912 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9914 LD->getMemOperand());
9920 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9921 if (MemVT != MVT::v16i1)
9930 EVT MemVT =
LD->getMemoryVT();
9932 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9933 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9934 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9935 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9938 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9939 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9944 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9945 auto Pair = LowerAEABIUnalignedLoad(
SDValue(
N, 0), DAG);
9947 Results.push_back(Pair.first);
9948 Results.push_back(Pair.second);
9955 EVT MemVT = ST->getMemoryVT();
9956 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9957 MemVT == MVT::v16i1) &&
9958 "Expected a predicate type!");
9959 assert(MemVT == ST->getValue().getValueType());
9960 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9961 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9966 SDValue Build = ST->getValue();
9967 if (MemVT != MVT::v16i1) {
9980 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9986 ST->getChain(), dl, GRP, ST->getBasePtr(),
9988 ST->getMemOperand());
9994 EVT MemVT =
ST->getMemoryVT();
9996 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9997 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
9998 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9999 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10000 SDNode *
N =
Op.getNode();
10013 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10014 MemVT,
ST->getMemOperand());
10015 }
else if (Subtarget->hasMVEIntegerOps() &&
10016 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10017 MemVT == MVT::v16i1))) {
10019 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
10020 return LowerAEABIUnalignedStore(
Op, DAG);
10027 (
N->getOpcode() == ARMISD::VMOVIMM &&
10033 MVT VT =
Op.getSimpleValueType();
10035 SDValue PassThru =
N->getPassThru();
10046 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10047 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10048 N->getExtensionType(),
N->isExpandingLoad());
10051 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
10053 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10060 if (!ST->hasMVEIntegerOps())
10064 unsigned BaseOpcode = 0;
10065 switch (
Op->getOpcode()) {
10081 unsigned NumActiveLanes = NumElts;
10083 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10084 NumActiveLanes == 2) &&
10085 "Only expected a power 2 vector size");
10089 while (NumActiveLanes > 4) {
10090 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10092 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10093 NumActiveLanes /= 2;
10097 if (NumActiveLanes == 4) {
10107 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10108 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10109 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10115 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10119 if (EltVT !=
Op->getValueType(0))
10126 if (!ST->hasMVEFloatOps())
10133 if (!ST->hasNEON())
10141 unsigned PairwiseIntrinsic = 0;
10142 switch (
Op->getOpcode()) {
10146 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10149 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10152 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10155 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10161 unsigned NumActiveLanes = NumElts;
10163 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10164 NumActiveLanes == 2) &&
10165 "Only expected a power 2 vector size");
10171 VT =
Lo.getValueType();
10173 NumActiveLanes /= 2;
10177 while (NumActiveLanes > 1) {
10179 NumActiveLanes /= 2;
10186 if (EltVT !=
Op.getValueType()) {
10187 unsigned Extend = 0;
10188 switch (
Op->getOpcode()) {
10200 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10245 const SDValue Ops[] = {RegClass, V0, SubReg0,
V1, SubReg1};
10251 SDLoc dl(V.getNode());
10252 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10262 assert(
N->getValueType(0) == MVT::i64 &&
10263 "AtomicCmpSwap on types less than 64 should be legal");
10272 ARM::CMP_SWAP_64,
SDLoc(
N),
10273 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10292 EVT VT =
Op.getValueType();
10301 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10303 Chain, IsSignaling);
10304 if (!
RHS.getNode()) {
10320 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10322 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10323 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10340 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10343 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10356 if (!IsSigned && Subtarget->isThumb1Only()) {
10374 Sub1Result, Sub1Result, Flags1);
10389 if (
Op.getValueType() != MVT::i32)
10403 unsigned Opcode = ARMISD::SUBC;
10412 bool CanUseAdd =
false;
10428 Opcode = ARMISD::ADDC;
10452 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10453 GTCondValue, Flags);
10457 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10458 LTCondValue, Flags);
10460 if (
Op.getValueType() != MVT::i32)
10468 switch (
Op.getOpcode()) {
10500 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10504 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10505 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10527 return LowerSET_FPMODE(
Op, DAG);
10529 return LowerRESET_FPMODE(
Op, DAG);
10533 !
Op.getValueType().isVector())
10534 return LowerDIV_Windows(
Op, DAG,
true);
10538 !
Op.getValueType().isVector())
10539 return LowerDIV_Windows(
Op, DAG,
false);
10555 return LowerALUO(
Op, DAG);
10563 EVT MemVT = LD->getMemoryVT();
10564 if (Subtarget->hasMVEIntegerOps() &&
10565 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10566 MemVT == MVT::v16i1))
10569 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10575 return LowerSTORE(
Op, DAG, Subtarget);
10600 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10609 return LowerSPONENTRY(
Op, DAG);
10611 return LowerFP_TO_BF16(
Op, DAG);
10612 case ARMISD::WIN__DBZCHK:
return SDValue();
10615 return LowerCMP(
Op, DAG);
10617 return LowerABS(
Op, DAG);
10622 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10623 Op.getOperand(1).getValueType() == MVT::bf16) &&
10624 "Expected custom lowering of rounding operations only for f16");
10627 {
Op.getOperand(0),
Op.getOperand(1)});
10628 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10629 {Ext.getValue(1), Ext.getValue(0)});
10636 unsigned IntNo =
N->getConstantOperandVal(0);
10638 if (IntNo == Intrinsic::arm_smlald)
10639 Opc = ARMISD::SMLALD;
10640 else if (IntNo == Intrinsic::arm_smlaldx)
10641 Opc = ARMISD::SMLALDX;
10642 else if (IntNo == Intrinsic::arm_smlsld)
10643 Opc = ARMISD::SMLSLD;
10644 else if (IntNo == Intrinsic::arm_smlsldx)
10645 Opc = ARMISD::SMLSLDX;
10651 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10655 N->getOperand(1),
N->getOperand(2),
10667 switch (
N->getOpcode()) {
10674 Res = ExpandBITCAST(
N, DAG, Subtarget);
10683 Res = LowerREM(
N, DAG);
10687 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10704 "can only expand DIV on Windows");
10716 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10745 "ROPI/RWPI not currently supported with SjLj");
10754 bool isThumb = Subtarget->isThumb();
10755 bool isThumb2 = Subtarget->
isThumb2();
10758 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10764 : &ARM::GPRRegClass;
10870 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10873 MachineRegisterInfo *MRI = &MF->
getRegInfo();
10877 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10878 : &ARM::GPRnopcRegClass;
10882 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10883 unsigned MaxCSNum = 0;
10884 for (MachineBasicBlock &BB : *MF) {
10890 for (MachineInstr &
II : BB) {
10891 if (!
II.isEHLabel())
10894 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10895 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10897 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10898 for (
unsigned Idx : CallSiteIdxs) {
10899 CallSiteNumToLPad[Idx].push_back(&BB);
10900 MaxCSNum = std::max(MaxCSNum, Idx);
10907 std::vector<MachineBasicBlock*> LPadList;
10908 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10909 LPadList.reserve(CallSiteNumToLPad.
size());
10910 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10911 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10912 for (MachineBasicBlock *
MBB : MBBList) {
10913 LPadList.push_back(
MBB);
10918 assert(!LPadList.empty() &&
10919 "No landing pad destinations for the dispatch jump table!");
10922 MachineJumpTableInfo *JTI =
10929 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10932 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10934 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10937 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10941 MF->insert(MF->end(), DispatchBB);
10942 MF->insert(MF->end(), DispContBB);
10943 MF->insert(MF->end(), TrapBB);
10947 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10949 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10953 MachineInstrBuilder MIB;
10954 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10956 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10966 unsigned NumLPads = LPadList.size();
10967 if (Subtarget->isThumb2()) {
10969 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10975 if (NumLPads < 256) {
10976 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10978 .
addImm(LPadList.size())
10982 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10983 .
addImm(NumLPads & 0xFFFF)
10986 unsigned VReg2 = VReg1;
10987 if ((NumLPads & 0xFFFF0000) != 0) {
10989 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10995 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11001 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11007 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11012 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11019 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11023 }
else if (Subtarget->isThumb()) {
11025 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11031 if (NumLPads < 256) {
11032 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11037 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11042 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11043 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11046 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11050 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11056 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11062 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11069 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11074 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11080 MachineMemOperand *JTMMOLd =
11085 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11091 unsigned NewVReg6 = NewVReg5;
11092 if (IsPositionIndependent) {
11094 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11101 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11106 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11112 if (NumLPads < 256) {
11113 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11117 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11119 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11120 .
addImm(NumLPads & 0xFFFF)
11123 unsigned VReg2 = VReg1;
11124 if ((NumLPads & 0xFFFF0000) != 0) {
11126 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11132 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11137 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11142 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11143 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11146 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11151 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11163 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11169 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11173 MachineMemOperand *JTMMOLd =
11177 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11184 if (IsPositionIndependent) {
11185 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11190 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11197 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11198 for (MachineBasicBlock *CurMBB : LPadList) {
11199 if (SeenMBBs.
insert(CurMBB).second)
11206 for (MachineBasicBlock *BB : InvokeBBs) {
11210 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11211 while (!Successors.empty()) {
11212 MachineBasicBlock *SMBB = Successors.pop_back_val();
11214 BB->removeSuccessor(SMBB);
11220 BB->normalizeSuccProbs();
11227 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11228 if (!
II->isCall())
continue;
11230 DenseSet<unsigned> DefRegs;
11232 OI =
II->operands_begin(), OE =
II->operands_end();
11234 if (!OI->isReg())
continue;
11235 DefRegs.
insert(OI->getReg());
11238 MachineInstrBuilder MIB(*MF, &*
II);
11240 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11241 unsigned Reg = SavedRegs[i];
11242 if (Subtarget->isThumb2() &&
11243 !ARM::tGPRRegClass.contains(
Reg) &&
11244 !ARM::hGPRRegClass.contains(
Reg))
11246 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11248 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11260 for (MachineBasicBlock *MBBLPad : MBBLPads)
11261 MBBLPad->setIsEHPad(
false);
11264 MI.eraseFromParent();
11277static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11279 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11280 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11282 return LdSize == 4 ? ARM::tLDRi
11283 : LdSize == 2 ? ARM::tLDRHi
11284 : LdSize == 1 ? ARM::tLDRBi : 0;
11286 return LdSize == 4 ? ARM::t2LDR_POST
11287 : LdSize == 2 ? ARM::t2LDRH_POST
11288 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11289 return LdSize == 4 ? ARM::LDR_POST_IMM
11290 : LdSize == 2 ? ARM::LDRH_POST
11291 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11296static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11298 return StSize == 16 ? ARM::VST1q32wb_fixed
11299 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11301 return StSize == 4 ? ARM::tSTRi
11302 : StSize == 2 ? ARM::tSTRHi
11303 : StSize == 1 ? ARM::tSTRBi : 0;
11305 return StSize == 4 ? ARM::t2STR_POST
11306 : StSize == 2 ? ARM::t2STRH_POST
11307 : StSize == 1 ? ARM::t2STRB_POST : 0;
11308 return StSize == 4 ? ARM::STR_POST_IMM
11309 : StSize == 2 ? ARM::STRH_POST
11310 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11317 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11318 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11319 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11320 assert(LdOpc != 0 &&
"Should have a load opcode");
11327 }
else if (IsThumb1) {
11333 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11338 }
else if (IsThumb2) {
11358 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11359 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11360 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11361 assert(StOpc != 0 &&
"Should have a store opcode");
11363 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11368 }
else if (IsThumb1) {
11375 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11380 }
else if (IsThumb2) {
11381 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11387 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11402 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11408 unsigned SizeVal =
MI.getOperand(2).getImm();
11409 unsigned Alignment =
MI.getOperand(3).getImm();
11413 MachineRegisterInfo &MRI = MF->
getRegInfo();
11414 unsigned UnitSize = 0;
11415 const TargetRegisterClass *TRC =
nullptr;
11416 const TargetRegisterClass *VecTRC =
nullptr;
11418 bool IsThumb1 = Subtarget->isThumb1Only();
11419 bool IsThumb2 = Subtarget->isThumb2();
11420 bool IsThumb = Subtarget->isThumb();
11422 if (Alignment & 1) {
11424 }
else if (Alignment & 2) {
11429 Subtarget->hasNEON()) {
11430 if ((Alignment % 16 == 0) && SizeVal >= 16)
11432 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11441 bool IsNeon = UnitSize >= 8;
11442 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11444 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11445 : UnitSize == 8 ? &ARM::DPRRegClass
11448 unsigned BytesLeft = SizeVal % UnitSize;
11449 unsigned LoopSize = SizeVal - BytesLeft;
11451 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11455 unsigned srcIn = src;
11456 unsigned destIn = dest;
11457 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11462 IsThumb1, IsThumb2);
11464 IsThumb1, IsThumb2);
11472 for (
unsigned i = 0; i < BytesLeft; i++) {
11477 IsThumb1, IsThumb2);
11479 IsThumb1, IsThumb2);
11483 MI.eraseFromParent();
11509 MF->
insert(It, loopMBB);
11510 MF->
insert(It, exitMBB);
11513 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11524 if (Subtarget->useMovt()) {
11525 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11528 }
else if (Subtarget->genExecuteOnly()) {
11529 assert(IsThumb &&
"Non-thumb expected to have used movt");
11538 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11539 MachineMemOperand *CPMMO =
11563 MachineBasicBlock *entryBB = BB;
11578 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11586 IsThumb1, IsThumb2);
11588 IsThumb1, IsThumb2);
11592 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11598 MachineInstrBuilder MIB =
11600 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11609 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11618 auto StartOfExit = exitMBB->
begin();
11622 unsigned srcIn = srcLoop;
11623 unsigned destIn = destLoop;
11624 for (
unsigned i = 0; i < BytesLeft; i++) {
11628 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11629 IsThumb1, IsThumb2);
11630 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11631 IsThumb1, IsThumb2);
11636 MI.eraseFromParent();
11644 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11647 assert(TM.getTargetTriple().isOSWindows() &&
11648 "__chkstk is only supported on Windows");
11649 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11669 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11670 if (ChkStkLibcall == RTLIB::Unsupported)
11674 switch (TM.getCodeModel()) {
11716 MI.eraseFromParent();
11725 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11740 .
addReg(
MI.getOperand(0).getReg())
11748 MI.eraseFromParent();
11772 if (miI == BB->
end()) {
11774 if (Succ->isLiveIn(ARM::CPSR))
11780 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11793 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11800 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11807 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11810 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11811 .
addUse(TotalIterationsReg)
11818 return TotalIterationsReg;
11829 Register TotalIterationsReg,
bool IsMemcpy) {
11838 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11848 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11856 Register RemainingLoopIterationsReg =
11858 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11859 .
addUse(TotalIterationsReg)
11861 .
addUse(RemainingLoopIterationsReg)
11867 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11868 .
addUse(ElementCountReg)
11870 .
addUse(RemainingElementsReg)
11875 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11876 .
addUse(PredCounterPhiReg)
11881 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11882 .
addUse(PredCounterPhiReg)
11891 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11900 SrcValueReg = OpSrcReg;
11902 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11913 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11914 .
addUse(LoopCounterPhiReg)
11917 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11918 .
addUse(RemainingLoopIterationsReg)
11936 "Invalid call instruction for a KCFI check");
11939 switch (
MBBI->getOpcode()) {
11942 case ARM::BLX_pred:
11943 case ARM::BLX_noip:
11944 case ARM::BLX_pred_noip:
11946 TargetOp = &
MBBI->getOperand(0);
11948 case ARM::TCRETURNri:
11949 case ARM::TCRETURNrinotr12:
11950 case ARM::TAILJMPr:
11951 case ARM::TAILJMPr4:
11952 TargetOp = &
MBBI->getOperand(0);
11958 case ARM::tBLXr_noip:
11959 case ARM::tBX_CALL:
11960 TargetOp = &
MBBI->getOperand(2);
11963 case ARM::tTAILJMPr:
11964 TargetOp = &
MBBI->getOperand(0);
11970 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11974 unsigned KCFICheckOpcode;
11975 if (Subtarget->isThumb()) {
11976 if (Subtarget->isThumb2()) {
11977 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11979 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11982 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11996 bool isThumb2 = Subtarget->isThumb2();
11997 switch (
MI.getOpcode()) {
12004 case ARM::tLDR_postidx: {
12008 .
add(
MI.getOperand(2))
12009 .
add(
MI.getOperand(3))
12010 .
add(
MI.getOperand(4))
12011 .
add(
MI.getOperand(0))
12013 MI.eraseFromParent();
12017 case ARM::MVE_MEMCPYLOOPINST:
12018 case ARM::MVE_MEMSETLOOPINST: {
12048 Register OpDestReg =
MI.getOperand(0).getReg();
12049 Register OpSrcReg =
MI.getOperand(1).getReg();
12050 Register OpSizeReg =
MI.getOperand(2).getReg();
12070 if (TpExit == BB) {
12072 "block containing memcpy/memset Pseudo");
12082 genTPEntry(TpEntry, TpLoopBody, TpExit, OpSizeReg,
TII, dl, MRI);
12085 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12087 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12090 Properties.resetNoPHIs();
12102 MI.eraseFromParent();
12112 case ARM::t2STR_preidx:
12113 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12115 case ARM::t2STRB_preidx:
12116 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12118 case ARM::t2STRH_preidx:
12119 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12122 case ARM::STRi_preidx:
12123 case ARM::STRBi_preidx: {
12124 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12125 : ARM::STRB_PRE_IMM;
12127 unsigned Offset =
MI.getOperand(4).getImm();
12135 .
add(
MI.getOperand(0))
12136 .
add(
MI.getOperand(1))
12137 .
add(
MI.getOperand(2))
12139 .
add(
MI.getOperand(5))
12140 .
add(
MI.getOperand(6))
12142 MI.eraseFromParent();
12145 case ARM::STRr_preidx:
12146 case ARM::STRBr_preidx:
12147 case ARM::STRH_preidx: {
12149 switch (
MI.getOpcode()) {
12151 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12152 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12153 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12158 MI.eraseFromParent();
12162 case ARM::tMOVCCr_pseudo: {
12180 F->insert(It, copy0MBB);
12181 F->insert(It, sinkMBB);
12184 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12190 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12206 .
addImm(
MI.getOperand(3).getImm())
12207 .
addReg(
MI.getOperand(4).getReg());
12222 .
addReg(
MI.getOperand(1).getReg())
12224 .
addReg(
MI.getOperand(2).getReg())
12227 MI.eraseFromParent();
12232 case ARM::BCCZi64: {
12238 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12243 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12247 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12253 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12257 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12267 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12276 MI.eraseFromParent();
12280 case ARM::Int_eh_sjlj_setjmp:
12281 case ARM::Int_eh_sjlj_setjmp_nofp:
12282 case ARM::tInt_eh_sjlj_setjmp:
12283 case ARM::t2Int_eh_sjlj_setjmp:
12284 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12287 case ARM::Int_eh_sjlj_setup_dispatch:
12288 EmitSjLjDispatchBlock(
MI, BB);
12290 case ARM::COPY_STRUCT_BYVAL_I32:
12292 return EmitStructByval(
MI, BB);
12293 case ARM::WIN__CHKSTK:
12294 return EmitLowered__chkstk(
MI, BB);
12295 case ARM::WIN__DBZCHK:
12296 return EmitLowered__dbzchk(
MI, BB);
12312 if (!
Node->hasAnyUseOfValue(0)) {
12313 MI.getOperand(0).setIsDead(
true);
12315 if (!
Node->hasAnyUseOfValue(1)) {
12316 MI.getOperand(1).setIsDead(
true);
12320 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12322 : &ARM::GPRRegClass);
12329 if (
MI.getOpcode() == ARM::MEMCPY) {
12350 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12351 &&
"converted opcode should be the same except for cc_out"
12352 " (and, on Thumb1, pred)");
12360 if (Subtarget->isThumb1Only()) {
12361 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12362 MI.addOperand(
MI.getOperand(1));
12363 MI.removeOperand(1);
12367 for (
unsigned i =
MI.getNumOperands(); i--;) {
12369 if (
op.isReg() &&
op.isUse()) {
12372 MI.tieOperands(DefIdx, i);
12380 ccOutIdx =
MCID->getNumOperands() - 1;
12382 ccOutIdx =
MCID->getNumOperands() - 1;
12386 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12387 assert(!NewOpc &&
"Optional cc_out operand required");
12392 bool definesCPSR =
false;
12393 bool deadCPSR =
false;
12394 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12398 definesCPSR =
true;
12401 MI.removeOperand(i);
12405 if (!definesCPSR) {
12406 assert(!NewOpc &&
"Optional cc_out operand required");
12409 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12411 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12412 "expect uninitialized optional cc_out operand");
12414 if (!Subtarget->isThumb1Only())
12450 switch (
N->getOpcode()) {
12451 default:
return false;
12453 CC =
N->getOperand(0);
12475 EVT VT =
N->getValueType(0);
12476 CC =
N->getOperand(0);
12523 EVT VT =
N->getValueType(0);
12526 bool SwapSelectOps;
12528 NonConstantVal, DAG))
12534 OtherOp, NonConstantVal);
12540 CCOp, TrueVal, FalseVal);
12560 if (
N->getOpcode() == ARMISD::VUZP)
12564 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12579 if (!
N->getValueType(0).is64BitVector())
12587 EVT VT =
N->getValueType(0);
12626 EVT VT =
N->getValueType(0);
12632 Opcode = Intrinsic::arm_neon_vpaddls;
12634 Opcode = Intrinsic::arm_neon_vpaddlu;
12662 EVT VT =
N->getValueType(0);
12677 unsigned nextIndex = 0;
12728 Ops.push_back(Vec);
12745 return DAG.
getNode(ExtOp, dl, VT, tmp);
12776 if (SRA.getOpcode() !=
ISD::SRA) {
12783 if (Const->getZExtValue() != 31)
12788 if (SRA.getOperand(0) !=
Mul)
12792 SDLoc dl(AddcNode);
12793 unsigned Opcode = 0;
12798 Opcode = ARMISD::SMLALBB;
12799 Op0 =
Mul.getOperand(0);
12800 Op1 =
Mul.getOperand(1);
12802 Opcode = ARMISD::SMLALBT;
12803 Op0 =
Mul.getOperand(0);
12804 Op1 =
Mul.getOperand(1).getOperand(0);
12806 Opcode = ARMISD::SMLALTB;
12807 Op0 =
Mul.getOperand(0).getOperand(0);
12808 Op1 =
Mul.getOperand(1);
12810 Opcode = ARMISD::SMLALTT;
12811 Op0 =
Mul->getOperand(0).getOperand(0);
12812 Op1 =
Mul->getOperand(1).getOperand(0);
12828 SDValue resNode(AddcNode, 0);
12856 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12857 "Expect an ADDE or SUBE");
12861 "ADDE node has the wrong inputs");
12865 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12866 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12867 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12868 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12880 "Expect ADDC with two result values. First: i32");
12884 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12900 bool IsLeftOperandMUL =
false;
12905 IsLeftOperandMUL =
true;
12916 SDValue *LowAddSub =
nullptr;
12919 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12922 if (IsLeftOperandMUL)
12923 HiAddSub = &AddeSubeOp1;
12925 HiAddSub = &AddeSubeOp0;
12930 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12931 LoMul = &AddcSubcOp0;
12932 LowAddSub = &AddcSubcOp1;
12934 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12935 LoMul = &AddcSubcOp1;
12936 LowAddSub = &AddcSubcOp0;
12944 if (AddcSubcNode == HiAddSub->getNode() ||
12960 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12965 Ops.push_back(*HiAddSub);
12966 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12967 FinalOpc = ARMISD::SMMLSR;
12969 FinalOpc = ARMISD::SMMLAR;
12974 return SDValue(AddeSubeNode, 0);
12975 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12981 Ops.push_back(*LowAddSub);
12982 Ops.push_back(*HiAddSub);
12995 return SDValue(AddeSubeNode, 0);
13007 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13012 if (AddcNode->
getOpcode() != ARMISD::ADDC)
13016 SDNode *UmlalNode =
nullptr;
13055 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13060 SDNode* AddcNode =
N->getOperand(2).getNode();
13061 SDNode* AddeNode =
N->getOperand(3).getNode();
13062 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
13063 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
13069 {N->getOperand(0), N->getOperand(1),
13070 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13080 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13084 if (
LHS->getOpcode() == ARMISD::ADDE &&
13094 int32_t imm =
C->getSExtValue();
13095 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13098 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13100 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13115 int64_t imm =
C->getSExtValue();
13124 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13126 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13127 N->getOperand(0),
RHS,
N->getOperand(2));
13139 if (!Subtarget->hasMVEIntegerOps())
13152 SetCC =
N->getOperand(0);
13156 TrueVal =
N->getOperand(1);
13157 FalseVal =
N->getOperand(2);
13159 LHS =
N->getOperand(0);
13160 RHS =
N->getOperand(1);
13162 TrueVal =
N->getOperand(2);
13163 FalseVal =
N->getOperand(3);
13168 unsigned int Opcode = 0;
13172 Opcode = ARMISD::VMINVu;
13178 Opcode = ARMISD::VMINVs;
13184 Opcode = ARMISD::VMAXVu;
13190 Opcode = ARMISD::VMAXVs;
13197 switch (TrueVal->getOpcode()) {
13216 if (TrueVal !=
LHS || FalseVal !=
RHS)
13219 EVT LeftType =
LHS->getValueType(0);
13220 EVT RightType =
RHS->getValueType(0);
13223 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13227 if (VectorScalarType != MVT::i32)
13235 if (VectorScalarType != MVT::i32)
13248 EVT VT =
N->getValueType(0);
13256 Shft =
N->getOperand(0);
13263 Cmp.getOperand(0) !=
N->getOperand(1) ||
13264 Cmp.getOperand(1) !=
N->getOperand(2))
13266 Shft =
N->getOperand(1);
13278 ScalarType = MVT::i8;
13281 case (1 << 15) - 1:
13282 ScalarType = MVT::i16;
13285 case (1ULL << 31) - 1:
13286 ScalarType = MVT::i32;
13317 unsigned LegalLanes = 128 / (ShftAmt + 1);
13329 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13330 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13331 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13332 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13341 for (
unsigned I = 0;
I < NumParts; ++
I) {
13348 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13358 if (!Subtarget->hasMVEIntegerOps())
13363 if (
N->getOperand(0).getOpcode() == ARMISD::PREDICATE_CAST &&
13365 unsigned C =
N->getOperand(0).getConstantOperandVal(0);
13367 return N->getOperand(2);
13369 return N->getOperand(1);
13384 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13394 if (!Const || !Const->isOne())
13412 EVT VT =
N->getValueType(0);
13414 if (!Subtarget->hasMVEIntegerOps() ||
13443 Opc = Intrinsic::arm_mve_vctp64;
13446 Opc = Intrinsic::arm_mve_vctp32;
13449 Opc = Intrinsic::arm_mve_vctp16;
13452 Opc = Intrinsic::arm_mve_vctp8;
13506 EVT VT =
N->getValueType(0);
13512 switch (
Op.getOpcode()) {
13514 case ARMISD::VADDVs:
13515 case ARMISD::VADDVu:
13516 case ARMISD::VMLAVs:
13517 case ARMISD::VMLAVu:
13537 unsigned N0RedOp = 0;
13544 unsigned N1RedOp = 0;
13558 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13560 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13567 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13591 if (!BaseLocDecomp0.getBase() ||
13592 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13593 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13595 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13597 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13607 if (IsBefore < 0) {
13610 }
else if (IsBefore > 0) {
13623 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13633 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13643 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13645 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13652 if (!Subtarget->hasMVEIntegerOps())
13658 EVT VT =
N->getValueType(0);
13663 if (VT != MVT::i64)
13674 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13694 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13703 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13705 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13707 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13709 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13711 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13713 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13715 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13717 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13719 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13721 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13723 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13725 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13727 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13729 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13731 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13733 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13743 "Expected shift op");
13745 SDValue ShiftLHS =
N->getOperand(0);
13759 if (Subtarget->isThumb1Only()) {
13770 if (Const->getAPIntValue().ult(256))
13773 Const->getAPIntValue().sgt(-256))
13789 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13790 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13791 "Expected XOR(SHIFT) pattern");
13796 if (XorC && ShiftC) {
13797 unsigned MaskIdx, MaskLen;
13798 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13799 unsigned ShiftAmt = ShiftC->getZExtValue();
13800 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13801 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13802 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13803 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13813 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13815 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13816 "Expected shift-shift mask");
13818 if (!Subtarget->isThumb1Only())
13821 EVT VT =
N->getValueType(0);
13829 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13831 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13836 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps()) {
13837 if (Subtarget->isThumb1Only())
13851 return Subtarget->hasVFP2Base();
13853 return Subtarget->hasVFP2Base();
13855 return Subtarget->hasFP64();
13858 return Subtarget->hasMVEFloatOps();
13887 if (ST->isThumb() && ST->isThumb1Only())
13891 for (
auto *U :
N->users()) {
13892 switch(U->getOpcode()) {
13910 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13911 U->getOperand(1).getOpcode() ==
ISD::SHL)
13921 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13928 if (!C1ShlC2 || !C2)
13931 APInt C2Int = C2->getAPIntValue();
13932 APInt C1Int = C1ShlC2->getAPIntValue();
13934 if (C2Int.
uge(C2Width))
13940 if ((C1Int & Mask) != C1Int)
13947 auto LargeImm = [](
const APInt &Imm) {
13948 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13949 return Imm.getBitWidth() - Zeros > 8;
13952 if (LargeImm(C1Int) || LargeImm(C2Int))
13964 SHL.dump();
N->dump());
14025 if (
Op.hasOneUse() && ShiftAmt &&
14026 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
14084 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14105 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14126 if (!Subtarget->hasVMLxForwarding())
14145 EVT VT =
N->getValueType(0);
14156 EVT VT =
N->getValueType(0);
14157 if (VT != MVT::v2i64)
14168 return Op->getOperand(0);
14182 And =
And->getOperand(0);
14187 Mask = Mask->getOperand(0);
14190 Mask.getValueType() != MVT::v4i32)
14196 return And->getOperand(0);
14201 if (
SDValue Op0 = IsSignExt(N0)) {
14202 if (
SDValue Op1 = IsSignExt(N1)) {
14203 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14204 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14205 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14208 if (
SDValue Op0 = IsZeroExt(N0)) {
14209 if (
SDValue Op1 = IsZeroExt(N1)) {
14210 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14211 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14212 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14224 EVT VT =
N->getValueType(0);
14225 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14236 if (VT != MVT::i32)
14243 int64_t MulAmt =
C->getSExtValue();
14246 ShiftAmt = ShiftAmt & (32 - 1);
14251 MulAmt >>= ShiftAmt;
14312 if (
N->getValueType(0) != MVT::i32)
14321 if (C1 == 255 || C1 == 65535)
14324 SDNode *N0 =
N->getOperand(0).getNode();
14338 if (!C2 || C2 >= 32)
14382 if (Trailing == C2 && C2 + C3 < 32) {
14395 if (Leading == C2 && C2 + C3 < 32) {
14423 EVT VT =
N->getValueType(0);
14427 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14430 APInt SplatBits, SplatUndef;
14431 unsigned SplatBitSize;
14433 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14434 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14435 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14436 SplatBitSize == 64) {
14443 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14445 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14470 if (!Subtarget->hasV6Ops() ||
14471 (Subtarget->isThumb() &&
14472 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14475 SDValue SRL = OR->getOperand(0);
14476 SDValue SHL = OR->getOperand(1);
14479 SRL = OR->getOperand(1);
14480 SHL = OR->getOperand(0);
14487 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14491 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14492 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14493 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14512 unsigned Opcode = 0;
14513 if (
isS16(OpS16, DAG))
14514 Opcode = ARMISD::SMULWB;
14516 Opcode = ARMISD::SMULWT;
14531 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14534 EVT VT =
N->getValueType(0);
14549 if (VT != MVT::i32)
14562 if (Mask == 0xffff)
14569 if ((Val & ~Mask) != Val)
14575 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14594 (Mask == ~Mask2)) {
14597 if (Subtarget->hasDSP() &&
14598 (Mask == 0xffff || Mask == 0xffff0000))
14604 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14611 (~Mask == Mask2)) {
14614 if (Subtarget->hasDSP() &&
14615 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14671 if (
N->getOpcode() == ARMISD::VCMP)
14673 else if (
N->getOpcode() == ARMISD::VCMPZ)
14681 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14688 EVT VT =
N->getValueType(0);
14693 auto IsFreelyInvertable = [&](
SDValue V) {
14694 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14700 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14718 if (AndOp.getOpcode() !=
ISD::AND)
14722 SDValue Mask = AndOp.getOperand(1);
14732 bool IsShiftRight =
false;
14735 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14736 IsShiftRight =
true;
14739 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14747 APInt RequiredMask = IsShiftRight
14750 if (MaskBits != RequiredMask)
14753 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14763 EVT VT =
N->getValueType(0);
14769 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14770 VT == MVT::v8i1 || VT == MVT::v16i1))
14773 APInt SplatBits, SplatUndef;
14774 unsigned SplatBitSize;
14776 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14777 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14778 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14779 SplatBitSize == 64) {
14786 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14788 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14808 (Subtarget->hasMVEIntegerOps() &&
14809 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14812 return ShiftInsert;
14816 return ShiftInsert;
14830 unsigned SplatBitSize;
14833 APInt SplatBits0, SplatBits1;
14837 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14838 HasAnyUndefs) && !HasAnyUndefs) {
14839 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14840 HasAnyUndefs) && !HasAnyUndefs) {
14845 SplatBits0 == ~SplatBits1) {
14853 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14873 if (CSINC.
getOpcode() != ARMISD::CSINC)
14875 if (CSINC.
getOpcode() == ARMISD::CSINC &&
14888 EVT VT =
N->getValueType(0);
14903 if (Subtarget->hasMVEIntegerOps()) {
14931 assert(
N->getOpcode() == ARMISD::BFI);
14934 ToMask =
~N->getConstantOperandAPInt(2);
14954 unsigned LastActiveBitInA =
A.countr_zero();
14955 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14956 return LastActiveBitInA - 1 == FirstActiveBitInB;
14961 APInt ToMask, FromMask;
14966 if (V.getOpcode() != ARMISD::BFI)
14969 APInt NewToMask, NewFromMask;
14971 if (NewFrom != From)
14975 if ((NewToMask & ToMask).getBoolValue())
15000 unsigned InvMask =
N->getConstantOperandVal(2);
15004 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
15005 "undefined behavior");
15006 unsigned Mask = (1u << Width) - 1;
15008 if ((Mask & (~Mask2)) == 0)
15010 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
15017 APInt ToMask1, FromMask1;
15020 APInt ToMask2, FromMask2;
15026 APInt NewFromMask = FromMask1 | FromMask2;
15027 APInt NewToMask = ToMask1 | ToMask2;
15029 EVT VT =
N->getValueType(0);
15032 if (NewFromMask[0] == 0)
15035 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
15043 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
15044 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
15045 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
15047 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
15051 EVT VT =
N->getValueType(0);
15054 N->getOperand(1),
N->getOperand(2));
15066 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
15068 SDValue CSInc = Cmp->getOperand(0);
15078 if (CSInc.
getOpcode() == ARMISD::CSINC &&
15118 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15119 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15122 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15124 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15137 SDValue InDouble =
N->getOperand(0);
15138 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15152 SDValue BasePtr = LD->getBasePtr();
15154 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15155 LD->getAlign(), LD->getMemOperand()->getFlags());
15161 LD->getPointerInfo().getWithOffset(4),
15163 LD->getMemOperand()->getFlags());
15182 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15196 if (!Subtarget->
isLittle() && BVSwap)
15214 if (!Subtarget->
isLittle() && BVSwap)
15233 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15246 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15259 if (Copy.getValueType() == MVT::f32 &&
15261 bool HasGlue = Copy->getNumOperands() == 3;
15262 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15263 HasGlue ? Copy->getOperand(2) :
SDValue()};
15264 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15283 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15284 LN0->getMemoryVT() == MVT::i16) {
15287 LN0->getBasePtr(), LN0->getMemOperand());
15305 EVT VT =
N->getValueType(0);
15339 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15340 for (
unsigned i = 0; i < NumElts; ++i) {
15341 SDNode *Elt =
N->getOperand(i).getNode();
15358 if (
N->getNumOperands() == 2)
15364 EVT VT =
N->getValueType(0);
15370 for (
unsigned i = 0; i < NumElts; ++i) {
15396 EVT VT =
N->getValueType(0);
15404 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15409 Use->getValueType(0).isFloatingPoint())
15417 unsigned NumOfBitCastedElts = 0;
15419 unsigned NumOfRelevantElts = NumElts;
15420 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15425 ++NumOfBitCastedElts;
15429 --NumOfRelevantElts;
15433 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15451 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15456 V->getOperand(0).getValueType() == MVT::i32)
15458 V = V.getOperand(0);
15475 EVT VT =
N->getValueType(0);
15480 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15482 if (
Op->getOperand(0).getValueType() == VT)
15483 return Op->getOperand(0);
15484 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15491 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15498 if (
Op.getValueType() == MVT::i32) {
15509 EVT VT =
N->getValueType(0);
15514 if (ST->isLittle())
15518 if (
Op.getValueType() == VT)
15525 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15527 if (
Op->getOperand(0).getValueType() == VT)
15528 return Op->getOperand(0);
15529 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15537 if (!Subtarget->hasMVEIntegerOps())
15540 EVT VT =
N->getValueType(0);
15548 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15554 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15558 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15571 EVT VT =
N->getValueType(0);
15572 SDNode *Elt =
N->getOperand(1).getNode();
15587 Vec, V,
N->getOperand(2));
15597 EVT VT =
N->getValueType(0);
15625 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15626 isa<ConstantSDNode>(V->getOperand(1)) &&
15627 V->getConstantOperandVal(1) == Lane + 1 &&
15628 V->getOperand(0).getResNo() == ResNo;
15630 if (OtherIt == Op0->
users().
end())
15635 SDValue OtherExt(*OtherIt, 0);
15647 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15650 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15660 EVT VT =
N->getValueType(0);
15664 if (Op0->
getOpcode() == ARMISD::VDUP) {
15666 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15667 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15668 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15669 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15670 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15673 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15674 X =
X->getOperand(0);
15675 if (
X.getValueType() == VT)
15683 return Op0.
getOperand(
N->getConstantOperandVal(1));
15693 unsigned Offset =
N->getConstantOperandVal(1);
15695 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15705 unsigned Idx =
N->getConstantOperandVal(1);
15720 unsigned Lane =
N->getConstantOperandVal(1);
15748 EVT VT =
N->getValueType(0);
15751 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15753 Op.getOperand(0).getValueType().getScalarType())
15754 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15763 SDValue SubVec =
N->getOperand(1);
15764 uint64_t IdxVal =
N->getConstantOperandVal(2);
15775 if (IdxVal == 0 && Vec.
isUndef())
15781 (IdxVal != 0 && IdxVal != NumSubElts))
15812 ARMISD::VMOVN,
DL, VT,
15818 ARMISD::VMOVN,
DL, VT,
15854 EVT VT =
N->getValueType(0);
15865 unsigned HalfElts = NumElts/2;
15867 for (
unsigned n = 0; n < NumElts; ++n) {
15870 if (MaskElt < (
int)HalfElts)
15872 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15873 NewElt = HalfElts + MaskElt - NumElts;
15916 bool SimpleConstIncOnly,
15924 bool isLoadOp =
true;
15925 bool isLaneOp =
false;
15928 bool hasAlignment =
true;
15929 unsigned NewOpc = 0;
15930 unsigned NumVecs = 0;
15931 if (
Target.isIntrinsic) {
15932 unsigned IntNo =
N->getConstantOperandVal(1);
15936 case Intrinsic::arm_neon_vld1:
15940 case Intrinsic::arm_neon_vld2:
15944 case Intrinsic::arm_neon_vld3:
15948 case Intrinsic::arm_neon_vld4:
15952 case Intrinsic::arm_neon_vld1x2:
15955 hasAlignment =
false;
15957 case Intrinsic::arm_neon_vld1x3:
15960 hasAlignment =
false;
15962 case Intrinsic::arm_neon_vld1x4:
15965 hasAlignment =
false;
15967 case Intrinsic::arm_neon_vld2dup:
15971 case Intrinsic::arm_neon_vld3dup:
15975 case Intrinsic::arm_neon_vld4dup:
15979 case Intrinsic::arm_neon_vld2lane:
15984 case Intrinsic::arm_neon_vld3lane:
15989 case Intrinsic::arm_neon_vld4lane:
15994 case Intrinsic::arm_neon_vst1:
15999 case Intrinsic::arm_neon_vst2:
16000 NewOpc = ARMISD::VST2_UPD;
16004 case Intrinsic::arm_neon_vst3:
16009 case Intrinsic::arm_neon_vst4:
16010 NewOpc = ARMISD::VST4_UPD;
16014 case Intrinsic::arm_neon_vst2lane:
16020 case Intrinsic::arm_neon_vst3lane:
16026 case Intrinsic::arm_neon_vst4lane:
16032 case Intrinsic::arm_neon_vst1x2:
16036 hasAlignment =
false;
16038 case Intrinsic::arm_neon_vst1x3:
16042 hasAlignment =
false;
16044 case Intrinsic::arm_neon_vst1x4:
16048 hasAlignment =
false;
16053 switch (
N->getOpcode()) {
16089 VecTy =
N->getValueType(0);
16090 }
else if (
Target.isIntrinsic) {
16091 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16094 "Node has to be a load, a store, or an intrinsic!");
16095 VecTy =
N->getOperand(1).getValueType();
16103 if (isLaneOp || isVLDDUPOp)
16106 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16112 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16121 EVT AlignedVecTy = VecTy;
16141 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16142 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16153 Alignment =
Align(1);
16159 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16161 for (n = 0; n < NumResultVecs; ++n)
16162 Tys[n] = AlignedVecTy;
16163 Tys[n++] = MVT::i32;
16164 Tys[n] = MVT::Other;
16169 Ops.push_back(
N->getOperand(0));
16170 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16175 Ops.push_back(StN->getValue());
16179 unsigned LastOperand =
16180 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16181 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16182 Ops.push_back(
N->getOperand(i));
16190 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16201 for (
unsigned i = 0; i < NumResultVecs; ++i)
16206 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16207 SDValue &LdVal = NewResults[0];
16243 switch (
N->getOpcode()) {
16247 *Ptr =
N->getOperand(0);
16248 *CInc =
N->getOperand(1);
16255 *Ptr =
N->getOperand(1);
16256 *CInc =
N->getOperand(2);
16283 SDValue Addr =
N->getOperand(AddrOpIdx);
16294 unsigned ConstInc =
16299 if (BaseUpdates.
size() >= MaxBaseUpdates)
16320 unsigned UserOffset =
16323 if (!UserOffset || UserOffset <=
Offset)
16326 unsigned NewConstInc = UserOffset -
Offset;
16329 if (BaseUpdates.
size() >= MaxBaseUpdates)
16337 unsigned NumValidUpd = BaseUpdates.
size();
16338 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16349 return LHS.ConstInc <
RHS.ConstInc;
16378 unsigned IntNo =
N->getConstantOperandVal(1);
16379 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16381 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16404 bool isLoadOp =
true;
16405 unsigned NewOpc = 0;
16406 unsigned NumVecs = 0;
16410 case Intrinsic::arm_mve_vld2q:
16414 case Intrinsic::arm_mve_vld4q:
16418 case Intrinsic::arm_mve_vst2q:
16419 NewOpc = ARMISD::VST2_UPD;
16423 case Intrinsic::arm_mve_vst4q:
16424 NewOpc = ARMISD::VST4_UPD;
16433 VecTy =
N->getValueType(0);
16435 VecTy =
N->getOperand(3).getValueType();
16449 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16451 for (n = 0; n < NumResultVecs; ++n)
16453 Tys[n++] = MVT::i32;
16454 Tys[n] = MVT::Other;
16459 Ops.push_back(
N->getOperand(0));
16460 Ops.push_back(
N->getOperand(2));
16461 Ops.push_back(Inc);
16463 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16464 Ops.push_back(
N->getOperand(i));
16471 for (
unsigned i = 0; i < NumResultVecs; ++i)
16490 EVT VT =
N->getValueType(0);
16496 SDNode *VLD =
N->getOperand(0).getNode();
16499 unsigned NumVecs = 0;
16500 unsigned NewOpc = 0;
16502 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16505 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16508 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16520 if (
Use.getResNo() == NumVecs)
16523 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16524 VLDLaneNo !=
User->getConstantOperandVal(1))
16531 for (n = 0; n < NumVecs; ++n)
16533 Tys[n] = MVT::Other;
16543 unsigned ResNo =
Use.getResNo();
16545 if (ResNo == NumVecs)
16552 std::vector<SDValue> VLDDupResults;
16553 for (
unsigned n = 0; n < NumVecs; ++n)
16567 EVT VT =
N->getValueType(0);
16570 if (Subtarget->hasMVEIntegerOps()) {
16574 ExtractVT = MVT::i32;
16576 N->getOperand(0),
N->getOperand(1));
16588 Op =
Op.getOperand(0);
16589 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16593 unsigned EltSize =
Op.getScalarValueSizeInBits();
16595 unsigned Imm =
Op.getConstantOperandVal(0);
16611 if (Subtarget->hasMVEIntegerOps()) {
16614 if (
Op.getValueType() == MVT::f32)
16615 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16617 else if (
Op.getValueType() == MVT::f16)
16618 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16619 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16622 if (!Subtarget->hasNEON())
16629 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16630 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16631 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16636 LD->getMemoryVT(), LD->getMemOperand());
16647 EVT VT =
N->getValueType(0);
16669 assert(StVT != VT &&
"Cannot truncate to the same type");
16679 if (0 != (NumElems * FromEltSz) % ToEltSz)
16682 unsigned SizeRatio = FromEltSz / ToEltSz;
16687 NumElems * SizeRatio);
16693 for (
unsigned i = 0; i < NumElems; ++i)
16707 MVT StoreType = MVT::i8;
16709 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16729 for (
unsigned I = 0;
I <
E;
I++) {
16760 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16763 unsigned NumElements = 4;
16780 unsigned Off0 = Rev ? NumElts : 0;
16781 unsigned Off1 = Rev ? 0 : NumElts;
16783 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16784 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16786 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16794 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16814 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16825 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16829 NewToVT, Alignment, MMOFlags, AAInfo);
16862 unsigned NewOffset =
16870 NewToVT, Alignment, MMOFlags, AAInfo);
16892 {Extract.getOperand(0), Extract.getOperand(1)});
16923 if (Subtarget->hasNEON())
16927 if (Subtarget->hasMVEFloatOps())
16931 if (Subtarget->hasMVEIntegerOps()) {
17006 if (!Subtarget->hasNEON())
17010 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
17018 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
17020 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
17021 uint32_t IntBits = IntTy.getSizeInBits();
17022 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17023 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17034 if (
C == -1 ||
C == 0 ||
C > 32)
17039 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
17040 Intrinsic::arm_neon_vcvtfp2fxu;
17043 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
17046 if (IntBits < FloatBits)
17054 if (!Subtarget->hasMVEFloatOps())
17062 EVT VT =
N->getValueType(0);
17067 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
17069 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
17071 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
17072 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
17074 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17087 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17098 EVT VT =
N->getValueType(0);
17101 if (!
N->getFlags().hasAllowReassociation())
17108 unsigned Opc =
A.getConstantOperandVal(0);
17109 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17114 A.getOperand(3),
A.getOperand(4));
17146 if (!Subtarget->hasNEON())
17150 unsigned OpOpcode =
Op.getNode()->getOpcode();
17151 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17155 SDValue ConstVec =
N->getOperand(1);
17159 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17161 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17162 uint32_t IntBits = IntTy.getSizeInBits();
17163 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17164 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17184 int32_t
C = IntVal.exactLogBase2();
17185 if (
C == -1 ||
C == 0 ||
C > 32)
17191 if (IntBits < FloatBits)
17193 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17195 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17196 : Intrinsic::arm_neon_vcvtfxu2fp;
17204 if (!ST->hasMVEIntegerOps())
17208 EVT ResVT =
N->getValueType(0);
17236 EVT AVT =
A.getValueType();
17242 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17243 EVT AVT =
A.getValueType();
17253 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17254 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17257 if (ExtTypeMatches(
A, ExtTypes))
17258 return ExtendIfNeeded(
A, ExtendCode);
17261 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17271 if (ExtTypeMatches(
A, ExtTypes))
17272 return ExtendIfNeeded(
A, ExtendCode);
17275 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17285 if (ResVT != RetTy)
17288 if (
Mul->getOpcode() == ExtendCode &&
17289 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17291 Mul =
Mul->getOperand(0);
17300 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17301 A = ExtendIfNeeded(
A, ExtendCode);
17302 B = ExtendIfNeeded(
B, ExtendCode);
17307 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17320 if (
Mul->getOpcode() == ExtendCode &&
17321 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17323 Mul =
Mul->getOperand(0);
17332 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17333 A = ExtendIfNeeded(
A, ExtendCode);
17334 B = ExtendIfNeeded(
B, ExtendCode);
17345 EVT VT =
Ops[0].getValueType();
17346 if (VT == MVT::v16i8) {
17347 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17348 "Unexpected illegal long reduction opcode");
17349 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17361 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17374 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17376 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17377 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17379 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17380 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17382 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17385 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17388 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17392 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17395 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17398 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17401 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17404 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17407 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17410 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17412 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17414 return Create64bitNode(ARMISD::VADDLVs, {
A});
17416 return Create64bitNode(ARMISD::VADDLVu, {
A});
17419 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17422 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17425 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17427 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17429 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17431 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17434 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17437 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17444 Op =
Op->getOperand(1);
17446 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17448 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17465 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17467 if (!Shuf || !Shuf->getOperand(1).isUndef())
17472 APInt SetElts(Mask.size(), 0);
17473 for (
int E : Mask) {
17481 if (
N->getNumOperands() != VecOp + 1) {
17483 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17489 if (
Op.getValueType().isVector())
17490 Ops.push_back(
Op.getOperand(0));
17501 unsigned IsTop =
N->getConstantOperandVal(2);
17508 if (Op0->
isUndef() && !IsTop)
17513 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17514 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17522 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17524 APInt Op0DemandedElts =
17525 IsTop ? Op1DemandedElts
17540 unsigned IsTop =
N->getConstantOperandVal(2);
17542 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17543 APInt Op0DemandedElts =
17555 EVT VT =
N->getValueType(0);
17562 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17563 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17567 LHS.getOperand(0),
RHS.getOperand(0));
17582 int ShiftAmt =
C->getSExtValue();
17583 if (ShiftAmt == 0) {
17589 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17590 unsigned NewOpcode =
17591 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17606 unsigned IntNo =
N->getConstantOperandVal(0);
17617 case Intrinsic::arm_neon_vshifts:
17618 case Intrinsic::arm_neon_vshiftu:
17619 case Intrinsic::arm_neon_vrshifts:
17620 case Intrinsic::arm_neon_vrshiftu:
17621 case Intrinsic::arm_neon_vrshiftn:
17622 case Intrinsic::arm_neon_vqshifts:
17623 case Intrinsic::arm_neon_vqshiftu:
17624 case Intrinsic::arm_neon_vqshiftsu:
17625 case Intrinsic::arm_neon_vqshiftns:
17626 case Intrinsic::arm_neon_vqshiftnu:
17627 case Intrinsic::arm_neon_vqshiftnsu:
17628 case Intrinsic::arm_neon_vqrshiftns:
17629 case Intrinsic::arm_neon_vqrshiftnu:
17630 case Intrinsic::arm_neon_vqrshiftnsu: {
17631 EVT VT =
N->getOperand(1).getValueType();
17633 unsigned VShiftOpc = 0;
17636 case Intrinsic::arm_neon_vshifts:
17637 case Intrinsic::arm_neon_vshiftu:
17639 VShiftOpc = ARMISD::VSHLIMM;
17642 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17643 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17644 : ARMISD::VSHRuIMM);
17649 case Intrinsic::arm_neon_vrshifts:
17650 case Intrinsic::arm_neon_vrshiftu:
17655 case Intrinsic::arm_neon_vqshifts:
17656 case Intrinsic::arm_neon_vqshiftu:
17661 case Intrinsic::arm_neon_vqshiftsu:
17666 case Intrinsic::arm_neon_vrshiftn:
17667 case Intrinsic::arm_neon_vqshiftns:
17668 case Intrinsic::arm_neon_vqshiftnu:
17669 case Intrinsic::arm_neon_vqshiftnsu:
17670 case Intrinsic::arm_neon_vqrshiftns:
17671 case Intrinsic::arm_neon_vqrshiftnu:
17672 case Intrinsic::arm_neon_vqrshiftnsu:
17684 case Intrinsic::arm_neon_vshifts:
17685 case Intrinsic::arm_neon_vshiftu:
17688 case Intrinsic::arm_neon_vrshifts:
17689 VShiftOpc = ARMISD::VRSHRsIMM;
17691 case Intrinsic::arm_neon_vrshiftu:
17692 VShiftOpc = ARMISD::VRSHRuIMM;
17694 case Intrinsic::arm_neon_vrshiftn:
17695 VShiftOpc = ARMISD::VRSHRNIMM;
17697 case Intrinsic::arm_neon_vqshifts:
17698 VShiftOpc = ARMISD::VQSHLsIMM;
17700 case Intrinsic::arm_neon_vqshiftu:
17701 VShiftOpc = ARMISD::VQSHLuIMM;
17703 case Intrinsic::arm_neon_vqshiftsu:
17704 VShiftOpc = ARMISD::VQSHLsuIMM;
17706 case Intrinsic::arm_neon_vqshiftns:
17707 VShiftOpc = ARMISD::VQSHRNsIMM;
17709 case Intrinsic::arm_neon_vqshiftnu:
17710 VShiftOpc = ARMISD::VQSHRNuIMM;
17712 case Intrinsic::arm_neon_vqshiftnsu:
17713 VShiftOpc = ARMISD::VQSHRNsuIMM;
17715 case Intrinsic::arm_neon_vqrshiftns:
17716 VShiftOpc = ARMISD::VQRSHRNsIMM;
17718 case Intrinsic::arm_neon_vqrshiftnu:
17719 VShiftOpc = ARMISD::VQRSHRNuIMM;
17721 case Intrinsic::arm_neon_vqrshiftnsu:
17722 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17727 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17728 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17731 case Intrinsic::arm_neon_vshiftins: {
17732 EVT VT =
N->getOperand(1).getValueType();
17734 unsigned VShiftOpc = 0;
17737 VShiftOpc = ARMISD::VSLIIMM;
17738 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17739 VShiftOpc = ARMISD::VSRIIMM;
17745 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17746 N->getOperand(1),
N->getOperand(2),
17750 case Intrinsic::arm_neon_vqrshifts:
17751 case Intrinsic::arm_neon_vqrshiftu:
17755 case Intrinsic::arm_neon_vbsl: {
17757 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17758 N->getOperand(2),
N->getOperand(3));
17760 case Intrinsic::arm_mve_vqdmlah:
17761 case Intrinsic::arm_mve_vqdmlash:
17762 case Intrinsic::arm_mve_vqrdmlah:
17763 case Intrinsic::arm_mve_vqrdmlash:
17764 case Intrinsic::arm_mve_vmla_n_predicated:
17765 case Intrinsic::arm_mve_vmlas_n_predicated:
17766 case Intrinsic::arm_mve_vqdmlah_predicated:
17767 case Intrinsic::arm_mve_vqdmlash_predicated:
17768 case Intrinsic::arm_mve_vqrdmlah_predicated:
17769 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17774 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17781 case Intrinsic::arm_mve_minv:
17782 case Intrinsic::arm_mve_maxv:
17783 case Intrinsic::arm_mve_minav:
17784 case Intrinsic::arm_mve_maxav:
17785 case Intrinsic::arm_mve_minv_predicated:
17786 case Intrinsic::arm_mve_maxv_predicated:
17787 case Intrinsic::arm_mve_minav_predicated:
17788 case Intrinsic::arm_mve_maxav_predicated: {
17791 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17798 case Intrinsic::arm_mve_addv: {
17801 bool Unsigned =
N->getConstantOperandVal(2);
17802 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17806 case Intrinsic::arm_mve_addlv:
17807 case Intrinsic::arm_mve_addlv_predicated: {
17810 bool Unsigned =
N->getConstantOperandVal(2);
17811 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17812 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17813 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17816 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17818 Ops.push_back(
N->getOperand(i));
17831 EVT VT =
Y.getValueType();
17834 if (Subtarget->hasMVEIntegerOps())
17836 if (Subtarget->hasNEON())
17850 EVT VT =
N->getValueType(0);
17852 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17853 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17854 N->getOperand(0)->hasOneUse()) {
17871 if (AndMask == 255 || AndMask == 65535)
17875 if (MaskedBits > ShiftAmt) {
17890 if (ST->hasMVEIntegerOps())
17895 switch (
N->getOpcode()) {
17901 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17908 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17909 unsigned VShiftOpc =
17910 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17912 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17928 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17931 EVT FromVT = LD->getValueType(0);
17932 EVT ToVT =
N->getValueType(0);
17939 unsigned NumElements = 0;
17940 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17942 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17944 if (NumElements == 0 ||
17954 SDValue BasePtr = LD->getBasePtr();
17955 Align Alignment = LD->getBaseAlign();
17976 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17977 Alignment, MMOFlags, AAInfo);
17983 if (FromEltVT == MVT::f16) {
17986 for (
unsigned i = 0; i < Loads.
size(); i++) {
17988 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
18007 EVT VT =
N->getValueType(0);
18014 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
18021 if (VT == MVT::i32 &&
18022 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
18027 switch (
N->getOpcode()) {
18030 Opc = ARMISD::VGETLANEs;
18034 Opc = ARMISD::VGETLANEu;
18041 if (ST->hasMVEIntegerOps())
18059 Ops.push_back(Ext);
18069 if (ST->hasMVEFloatOps())
18080 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
18084 EVT VT =
Op.getValueType();
18087 if (VT != MVT::i32 ||
18100 APInt MaxC = Max.getConstantOperandAPInt(1);
18103 !(MinC + 1).isPowerOf2())
18121 EVT VT =
N->getValueType(0);
18124 if (VT == MVT::i32)
18127 if (!ST->hasMVEIntegerOps())
18133 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18136 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18144 if (VT == MVT::v4i32)
18145 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18147 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18154 MaxC != ~SaturateC)
18159 if (IsSignedSaturate(
N, N0.
getNode())) {
18162 if (VT == MVT::v4i32) {
18163 HalfVT = MVT::v8i16;
18164 ExtVT = MVT::v4i16;
18166 HalfVT = MVT::v16i8;
18181 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18187 if (VT == MVT::v4i32)
18188 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18190 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18199 if (IsUnsignedSaturate(
N)) {
18203 if (VT == MVT::v4i32) {
18204 HalfVT = MVT::v8i16;
18205 ExtConst = 0x0000FFFF;
18207 HalfVT = MVT::v16i8;
18229 const APInt *CV = &
C->getAPIntValue();
18286 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18293 if ((OrCI & Known.
Zero) != OrCI)
18299 EVT VT =
X.getValueType();
18300 unsigned BitInX = AndC->
logBase2();
18308 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18309 BitInY < NumActiveBits; ++BitInY) {
18310 if (OrCI[BitInY] == 0)
18313 Mask.setBit(BitInY);
18314 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18330 switch (
N->getOpcode()) {
18345 if (Const->isZero())
18347 else if (Const->isOne())
18355 unsigned IntOp =
N.getConstantOperandVal(1);
18356 if (IntOp != Intrinsic::test_start_loop_iterations &&
18357 IntOp != Intrinsic::loop_decrement_reg)
18383 bool Negate =
false;
18389 Cond =
N->getOperand(1);
18390 Dest =
N->getOperand(2);
18394 Cond =
N->getOperand(2);
18395 Dest =
N->getOperand(4);
18397 if (!Const->isOne() && !Const->isZero())
18399 Imm = Const->getZExtValue();
18427 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18428 "unsupported condition");
18433 unsigned IntOp =
Int->getConstantOperandVal(1);
18434 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18435 "expected single br user");
18436 SDNode *Br = *
N->user_begin();
18446 if (IntOp == Intrinsic::test_start_loop_iterations) {
18448 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18450 if (IsTrueIfZero(CC, Imm)) {
18452 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18456 UpdateUncondBr(Br, Dest, DAG);
18458 SDValue Ops[] = {Chain, Setup, OtherTarget};
18459 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18471 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18475 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18479 if (
Target == OtherTarget)
18480 UpdateUncondBr(Br, Dest, DAG);
18486 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18495 if (Cmp.getOpcode() != ARMISD::CMPZ)
18500 SDValue LHS = Cmp.getOperand(0);
18501 SDValue RHS = Cmp.getOperand(1);
18510 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18511 LHS->getOperand(0)->hasOneUse() &&
18515 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18527 EVT VT =
N->getValueType(0);
18528 SDValue FalseVal =
N->getOperand(0);
18529 SDValue TrueVal =
N->getOperand(1);
18537 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18544 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18547 if (Cmp.getOpcode() != ARMISD::CMPZ)
18551 SDValue LHS = Cmp.getOperand(0);
18552 SDValue RHS = Cmp.getOperand(1);
18556 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18580 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18581 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18582 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18585 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18590 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18593 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18594 LHS->getOperand(2), LHS->getOperand(3));
18604 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18608 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18610 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18619 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18652 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18664 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18684 const APInt *TrueConst;
18685 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18686 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18687 FalseVal.getOperand(1) == RHS) ||
18691 unsigned ShiftAmount = TrueConst->
logBase2();
18706 if (Known.
Zero == 0xfffffffe)
18709 else if (Known.
Zero == 0xffffff00)
18712 else if (Known.
Zero == 0xffff0000)
18725 EVT DstVT =
N->getValueType(0);
18728 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18729 EVT SrcVT = Src.getValueType();
18731 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18736 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18737 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18738 Src.getValueType().getScalarSizeInBits())
18739 Src = Src.getOperand(0);
18743 EVT SrcVT = Src.getValueType();
18744 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18745 Src.getOpcode() == ARMISD::VMVNIMM ||
18746 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18749 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18763 EVT VT =
N->getValueType(0);
18771 if (
N->getNumOperands() == 2 &&
18775 N->getOperand(0).getOperand(1),
18776 N->getOperand(1).getOperand(0),
18777 N->getOperand(1).getOperand(1));
18780 if (
N->getNumOperands() == 2 &&
18786 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18787 S0->getOperand(1) ==
S1->getOperand(1)) {
18790 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18794 ARMISD::VMOVN,
DL, VT,
18795 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18796 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18800 ARMISD::VMOVN,
DL, VT,
18801 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18802 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18810 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18811 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18812 (Op.getOpcode() == ISD::BITCAST &&
18813 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18816 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18818 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18836 int NumIns =
N->getNumOperands();
18837 assert((NumIns == 2 || NumIns == 4) &&
18838 "Expected 2 or 4 inputs to an MVETrunc");
18840 if (
N->getNumOperands() == 4)
18844 for (
int I = 0;
I < NumIns;
I++) {
18846 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18851 Ptr, MPI, StoreVT,
Align(4));
18866 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18869 EVT FromVT = LD->getMemoryVT();
18870 EVT ToVT =
N->getValueType(0);
18877 unsigned NumElements = 0;
18878 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18880 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18882 assert(NumElements != 0);
18888 LD->getExtensionType() != NewExtType)
18895 SDValue BasePtr = LD->getBasePtr();
18896 Align Alignment = LD->getBaseAlign();
18915 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18916 Alignment, MMOFlags, AAInfo);
18932 EVT VT =
N->getValueType(0);
18934 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18935 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18937 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18939 auto Extend = [&](
SDValue V) {
18948 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
18949 SDValue Ext = Extend(
N->getOperand(0));
18957 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18958 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
18962 auto CheckInregMask = [&](
int Start,
int Offset) {
18964 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18970 if (CheckInregMask(0, 0))
18972 else if (CheckInregMask(0, 1))
18973 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18974 else if (CheckInregMask(0, Mask.size()))
18976 else if (CheckInregMask(0, Mask.size() + 1))
18977 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18982 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18986 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18993 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
19004 int NumOuts =
N->getNumValues();
19005 assert((NumOuts == 2 || NumOuts == 4) &&
19006 "Expected 2 or 4 outputs to an MVEEXT");
19007 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
19009 if (
N->getNumOperands() == 4)
19015 StackPtr, MPI,
Align(4));
19018 for (
int I = 0;
I < NumOuts;
I++) {
19020 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
19021 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
19026 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
19035 switch (
N->getOpcode()) {
19095 case ARMISD::BRCOND:
19099 case ARMISD::CSINC:
19100 case ARMISD::CSINV:
19101 case ARMISD::CSNEG:
19114 case ARMISD::PREDICATE_CAST:
19116 case ARMISD::VECTOR_REG_CAST:
19127 case ARMISD::VADDVs:
19128 case ARMISD::VADDVu:
19129 case ARMISD::VADDLVs:
19130 case ARMISD::VADDLVu:
19131 case ARMISD::VADDLVAs:
19132 case ARMISD::VADDLVAu:
19133 case ARMISD::VMLAVs:
19134 case ARMISD::VMLAVu:
19135 case ARMISD::VMLALVs:
19136 case ARMISD::VMLALVu:
19137 case ARMISD::VMLALVAs:
19138 case ARMISD::VMLALVAu:
19140 case ARMISD::VMOVN:
19142 case ARMISD::VQMOVNs:
19143 case ARMISD::VQMOVNu:
19145 case ARMISD::VQDMULH:
19151 case ARMISD::SMULWB: {
19152 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19158 case ARMISD::SMULWT: {
19159 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19165 case ARMISD::SMLALBB:
19166 case ARMISD::QADD16b:
19167 case ARMISD::QSUB16b:
19168 case ARMISD::UQADD16b:
19169 case ARMISD::UQSUB16b: {
19170 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19177 case ARMISD::SMLALBT: {
19178 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19180 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19187 case ARMISD::SMLALTB: {
19188 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19190 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19197 case ARMISD::SMLALTT: {
19198 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19205 case ARMISD::QADD8b:
19206 case ARMISD::QSUB8b:
19207 case ARMISD::UQADD8b:
19208 case ARMISD::UQSUB8b: {
19209 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19217 if (
N->getOperand(1) ==
N->getOperand(2))
19218 return N->getOperand(1);
19222 switch (
N->getConstantOperandVal(1)) {
19223 case Intrinsic::arm_neon_vld1:
19224 case Intrinsic::arm_neon_vld1x2:
19225 case Intrinsic::arm_neon_vld1x3:
19226 case Intrinsic::arm_neon_vld1x4:
19227 case Intrinsic::arm_neon_vld2:
19228 case Intrinsic::arm_neon_vld3:
19229 case Intrinsic::arm_neon_vld4:
19230 case Intrinsic::arm_neon_vld2lane:
19231 case Intrinsic::arm_neon_vld3lane:
19232 case Intrinsic::arm_neon_vld4lane:
19233 case Intrinsic::arm_neon_vld2dup:
19234 case Intrinsic::arm_neon_vld3dup:
19235 case Intrinsic::arm_neon_vld4dup:
19236 case Intrinsic::arm_neon_vst1:
19237 case Intrinsic::arm_neon_vst1x2:
19238 case Intrinsic::arm_neon_vst1x3:
19239 case Intrinsic::arm_neon_vst1x4:
19240 case Intrinsic::arm_neon_vst2:
19241 case Intrinsic::arm_neon_vst3:
19242 case Intrinsic::arm_neon_vst4:
19243 case Intrinsic::arm_neon_vst2lane:
19244 case Intrinsic::arm_neon_vst3lane:
19245 case Intrinsic::arm_neon_vst4lane:
19247 case Intrinsic::arm_mve_vld2q:
19248 case Intrinsic::arm_mve_vld4q:
19249 case Intrinsic::arm_mve_vst2q:
19250 case Intrinsic::arm_mve_vst4q:
19267 unsigned *
Fast)
const {
19273 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19276 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19278 if (AllowsUnaligned) {
19280 *
Fast = Subtarget->hasV7Ops();
19285 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19289 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19296 if (!Subtarget->hasMVEIntegerOps())
19300 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19301 Ty == MVT::v2i1)) {
19309 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19325 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19326 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19327 Ty == MVT::v2f64) {
19338 const AttributeList &FuncAttributes)
const {
19340 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19341 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19343 if (
Op.size() >= 16 &&
19349 }
else if (
Op.size() >= 8 &&
19366 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19368 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19370 return (SrcBits == 64 && DestBits == 32);
19379 return (SrcBits == 64 && DestBits == 32);
19415 return Subtarget->hasFullFP16();
19422 if (!Subtarget->hasMVEIntegerOps())
19441 if (Ld->isExpandingLoad())
19445 if (Subtarget->hasMVEIntegerOps())
19458 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19490bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19492 if (Subtarget->useSoftFloat())
19501 return Subtarget->hasMVEFloatOps();
19519 unsigned Scale = 1;
19536 if ((V & (Scale - 1)) != 0)
19545 if (VT.
isVector() && Subtarget->hasNEON())
19548 !Subtarget->hasMVEFloatOps())
19551 bool IsNeg =
false;
19557 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19560 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19576 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19582 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19612 default:
return false;
19631 int Scale = AM.
Scale;
19636 default:
return false;
19644 Scale = Scale & ~1;
19645 return Scale == 2 || Scale == 4 || Scale == 8;
19662 if (Scale & 1)
return false;
19669 const int Scale = AM.
Scale;
19679 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19695 switch (AM.
Scale) {
19706 if (Subtarget->isThumb1Only())
19709 if (Subtarget->isThumb2())
19712 int Scale = AM.
Scale;
19714 default:
return false;
19718 if (Scale < 0) Scale = -Scale;
19726 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19739 if (Scale & 1)
return false;
19752 if (!Subtarget->isThumb())
19755 if (Subtarget->isThumb2())
19759 return Imm >= 0 && Imm <= 255;
19769 if (!Subtarget->isThumb())
19771 if (Subtarget->isThumb2())
19774 return AbsImm <= 255;
19809 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19813 int RHSC = (int)
RHS->getZExtValue();
19814 if (RHSC < 0 && RHSC > -256) {
19824 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19827 int RHSC = (int)
RHS->getZExtValue();
19828 if (RHSC < 0 && RHSC > -0x1000) {
19870 int RHSC = (int)
RHS->getZExtValue();
19871 if (RHSC < 0 && RHSC > -0x100) {
19876 }
else if (RHSC > 0 && RHSC < 0x100) {
19887 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19898 bool CanChangeType = isLE && !IsMasked;
19901 int RHSC = (int)
RHS->getZExtValue();
19903 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19904 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19909 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19920 if (VT == MVT::v4i16) {
19921 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19923 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19924 if (IsInRange(RHSC, 0x80, 1))
19926 }
else if (Alignment >= 4 &&
19927 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19928 IsInRange(RHSC, 0x80, 4))
19930 else if (Alignment >= 2 &&
19931 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19932 IsInRange(RHSC, 0x80, 2))
19934 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19947 if (Subtarget->isThumb1Only())
19954 bool isSEXTLoad =
false;
19955 bool IsMasked =
false;
19957 Ptr = LD->getBasePtr();
19958 VT = LD->getMemoryVT();
19959 Alignment = LD->getAlign();
19960 AS = LD->getAddressSpace();
19963 Ptr = ST->getBasePtr();
19964 VT = ST->getMemoryVT();
19965 Alignment = ST->getAlign();
19966 AS = ST->getAddressSpace();
19968 Ptr = LD->getBasePtr();
19969 VT = LD->getMemoryVT();
19970 Alignment = LD->getAlign();
19971 AS = LD->getAddressSpace();
19975 Ptr = ST->getBasePtr();
19976 VT = ST->getMemoryVT();
19977 Alignment = ST->getAlign();
19978 AS = ST->getAddressSpace();
19993 bool isLegal =
false;
19995 isLegal = Subtarget->hasMVEIntegerOps() &&
19997 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19998 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
20000 if (Subtarget->isThumb2())
20025 bool isSEXTLoad =
false, isNonExt;
20026 bool IsMasked =
false;
20028 VT = LD->getMemoryVT();
20029 Ptr = LD->getBasePtr();
20030 Alignment = LD->getAlign();
20034 VT = ST->getMemoryVT();
20035 Ptr = ST->getBasePtr();
20036 Alignment = ST->getAlign();
20037 isNonExt = !ST->isTruncatingStore();
20039 VT = LD->getMemoryVT();
20040 Ptr = LD->getBasePtr();
20041 Alignment = LD->getAlign();
20046 VT = ST->getMemoryVT();
20047 Ptr = ST->getBasePtr();
20048 Alignment = ST->getAlign();
20049 isNonExt = !ST->isTruncatingStore();
20054 if (Subtarget->isThumb1Only()) {
20057 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
20058 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
20061 if (!RHS || RHS->getZExtValue() != 4)
20063 if (Alignment <
Align(4))
20067 Base =
Op->getOperand(0);
20073 bool isLegal =
false;
20075 isLegal = Subtarget->hasMVEIntegerOps() &&
20080 if (Subtarget->isThumb2())
20094 !Subtarget->isThumb2())
20108 const APInt &DemandedElts,
20110 unsigned Depth)
const {
20113 switch (
Op.getOpcode()) {
20120 if (
Op.getResNo() == 0) {
20131 case ARMISD::CMOV: {
20146 case Intrinsic::arm_ldaex:
20147 case Intrinsic::arm_ldrex: {
20155 case ARMISD::BFI: {
20162 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20163 Known.
Zero &= Mask;
20167 case ARMISD::VGETLANEs:
20168 case ARMISD::VGETLANEu: {
20169 const SDValue &SrcSV =
Op.getOperand(0);
20175 "VGETLANE index out of bounds");
20180 EVT VT =
Op.getValueType();
20186 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20187 Known = Known.
sext(DstSz);
20189 Known = Known.
zext(DstSz);
20194 case ARMISD::VMOVrh: {
20197 Known = KnownOp.
zext(32);
20200 case ARMISD::CSINC:
20201 case ARMISD::CSINV:
20202 case ARMISD::CSNEG: {
20210 if (
Op.getOpcode() == ARMISD::CSINC)
20213 else if (
Op.getOpcode() == ARMISD::CSINV)
20215 else if (
Op.getOpcode() == ARMISD::CSNEG)
20222 case ARMISD::VORRIMM:
20223 case ARMISD::VBICIMM: {
20224 unsigned Encoded =
Op.getConstantOperandVal(1);
20225 unsigned DecEltBits = 0;
20228 unsigned EltBits =
Op.getScalarValueSizeInBits();
20229 if (EltBits != DecEltBits) {
20238 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20239 APInt Imm(DecEltBits, DecodedVal);
20241 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20242 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20250 if (!Subtarget->isThumb())
20267 if (Imm == 0 || Imm == ~0U)
20270 unsigned Opc =
Op.getOpcode();
20272 EVT VT =
Op.getValueType();
20274 unsigned ShrunkImm = Imm & Demanded;
20275 unsigned ExpandedImm = Imm | ~Demanded;
20277 auto IsLegalImm = [ShrunkImm, ExpandedImm](
unsigned CandidateImm) ->
bool {
20278 return (ShrunkImm & CandidateImm) == ShrunkImm &&
20279 (~ExpandedImm & CandidateImm) == 0;
20281 auto UseImm = [Imm,
Opc,
Op, VT, &TLO](
unsigned NewImm) ->
bool {
20293 if (ShrunkImm == 0) {
20294 ++NumOptimizedImms;
20295 return UseImm(ShrunkImm);
20301 if (ExpandedImm == ~0U) {
20302 ++NumOptimizedImms;
20303 return UseImm(ExpandedImm);
20311 if (IsLegalImm(0xFF)) {
20312 ++NumOptimizedImms;
20313 return UseImm(0xFF);
20316 if (IsLegalImm(0xFFFF)) {
20317 ++NumOptimizedImms;
20318 return UseImm(0xFFFF);
20332 ++NumOptimizedImms;
20333 return UseImm(ShrunkImm);
20341 if ((~ExpandedImm) < 256) {
20342 ++NumOptimizedImms;
20343 return UseImm(ExpandedImm);
20349 !Subtarget->hasV6Ops()) {
20350 ++NumOptimizedImms;
20351 return UseImm(ExpandedImm);
20370 EVT VT =
Op.getValueType();
20385 switch (
Op.getOpcode()) {
20396 unsigned Imm =
C->getZExtValue();
20403 unsigned Depth)
const {
20404 unsigned Opc =
Op.getOpcode();
20408 case ARMISD::LSRL: {
20412 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20414 unsigned ShAmt =
Op->getConstantOperandVal(2);
20424 case ARMISD::VBICIMM: {
20426 unsigned ModImm =
Op.getConstantOperandVal(1);
20427 unsigned EltBits = 0;
20429 if ((OriginalDemandedBits & Mask) == 0)
20435 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20450 if (!Subtarget->hasVFP2Base())
20454 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20466 unsigned S = Constraint.
size();
20468 switch (Constraint[0]) {
20480 }
else if (S == 2) {
20481 switch (Constraint[0]) {
20498 Value *CallOperandVal =
info.CallOperandVal;
20501 if (!CallOperandVal)
20505 switch (*constraint) {
20511 if (Subtarget->isThumb())
20526 if (PR == 0 || VT == MVT::Other)
20528 if (ARM::SPRRegClass.
contains(PR))
20529 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20530 if (ARM::DPRRegClass.
contains(PR))
20535using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20539 switch (Constraint.
size()) {
20542 switch (Constraint[0]) {
20544 if (Subtarget->isThumb())
20545 return RCPair(0U, &ARM::tGPRRegClass);
20546 return RCPair(0U, &ARM::GPRRegClass);
20548 if (Subtarget->isThumb())
20549 return RCPair(0U, &ARM::hGPRRegClass);
20552 if (Subtarget->isThumb1Only())
20553 return RCPair(0U, &ARM::tGPRRegClass);
20554 return RCPair(0U, &ARM::GPRRegClass);
20556 if (VT == MVT::Other)
20558 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20559 return RCPair(0U, &ARM::SPRRegClass);
20561 return RCPair(0U, &ARM::DPRRegClass);
20563 return RCPair(0U, &ARM::QPRRegClass);
20566 if (VT == MVT::Other)
20568 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20569 return RCPair(0U, &ARM::SPR_8RegClass);
20571 return RCPair(0U, &ARM::DPR_8RegClass);
20573 return RCPair(0U, &ARM::QPR_8RegClass);
20576 if (VT == MVT::Other)
20578 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20579 return RCPair(0U, &ARM::SPRRegClass);
20581 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20583 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20589 if (Constraint[0] ==
'T') {
20590 switch (Constraint[1]) {
20594 return RCPair(0U, &ARM::tGPREvenRegClass);
20596 return RCPair(0U, &ARM::tGPROddRegClass);
20605 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20606 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20609 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20610 return std::make_pair(
unsigned(ARM::LR),
getRegClassFor(MVT::i32));
20614 return {0,
nullptr};
20622 std::vector<SDValue> &
Ops,
20627 if (Constraint.
size() != 1)
20630 char ConstraintLetter = Constraint[0];
20631 switch (ConstraintLetter) {
20634 case 'I':
case 'J':
case 'K':
case 'L':
20635 case 'M':
case 'N':
case 'O':
20640 int64_t CVal64 =
C->getSExtValue();
20641 int CVal = (int) CVal64;
20644 if (CVal != CVal64)
20647 switch (ConstraintLetter) {
20651 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20652 if (CVal >= 0 && CVal <= 65535)
20656 if (Subtarget->isThumb1Only()) {
20659 if (CVal >= 0 && CVal <= 255)
20661 }
else if (Subtarget->isThumb2()) {
20675 if (Subtarget->isThumb1Only()) {
20680 if (CVal >= -255 && CVal <= -1)
20686 if (CVal >= -4095 && CVal <= 4095)
20692 if (Subtarget->isThumb1Only()) {
20699 }
else if (Subtarget->isThumb2()) {
20719 if (Subtarget->isThumb1Only()) {
20722 if (CVal >= -7 && CVal < 7)
20724 }
else if (Subtarget->isThumb2()) {
20744 if (Subtarget->isThumb1Only()) {
20747 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20753 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20759 if (Subtarget->isThumb1Only()) {
20761 if (CVal >= 0 && CVal <= 31)
20767 if (Subtarget->isThumb1Only()) {
20770 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20779 if (Result.getNode()) {
20780 Ops.push_back(Result);
20790 "Unhandled Opcode in getDivRemLibcall");
20796 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20797 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20798 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20799 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20808 "Unhandled Opcode in getDivRemArgList");
20812 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20813 EVT ArgVT =
N->getOperand(i).getValueType();
20818 Args.push_back(Entry);
20826 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20827 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20828 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20829 "Register-based DivRem lowering only");
20830 unsigned Opcode =
Op->getOpcode();
20832 "Invalid opcode for Div/Rem lowering");
20834 EVT VT =
Op->getValueType(0);
20856 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20857 : Subtarget->hasDivideInARMMode();
20858 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20859 Op->getSimpleValueType(0) == MVT::i32) {
20861 const SDValue Dividend =
Op->getOperand(0);
20862 const SDValue Divisor =
Op->getOperand(1);
20863 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20867 SDValue Values[2] = {Div, Rem};
20886 if (
getTM().getTargetTriple().isOSWindows())
20889 TargetLowering::CallLoweringInfo CLI(DAG);
20893 Callee, std::move(Args))
20898 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20899 return CallInfo.first;
20905 EVT VT =
N->getValueType(0);
20911 Result[0], Result[1]);
20915 std::vector<Type*> RetTyParams;
20916 Type *RetTyElement;
20926 RetTyParams.push_back(RetTyElement);
20927 RetTyParams.push_back(RetTyElement);
20942 if (
getTM().getTargetTriple().isOSWindows())
20949 Callee, std::move(Args))
20953 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20956 SDNode *ResNode = CallResult.first.getNode();
20963 assert(
getTM().getTargetTriple().isOSWindows() &&
20964 "unsupported target platform");
20972 "no-stack-arg-probe")) {
20976 Chain =
SP.getValue(1);
20993 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20994 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
21004 bool IsStrict =
Op->isStrictFPOpcode();
21005 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21006 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21008 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
21009 "Unexpected type for custom-lowering FP_EXTEND");
21011 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21012 "With both FP DP and 16, any FP conversion is legal!");
21014 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
21015 "With FP16, 16 to 32 conversion is legal!");
21018 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
21023 Loc,
Op.getValueType(), SrcVal);
21038 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
21039 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
21040 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
21041 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
21045 {DstVT, MVT::Other}, {Chain, SrcVal});
21052 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21053 "Unexpected type for custom-lowering FP_EXTEND");
21054 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21059 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
21063 bool IsStrict =
Op->isStrictFPOpcode();
21065 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
21067 EVT DstVT =
Op.getValueType();
21068 const unsigned DstSz =
Op.getValueType().getSizeInBits();
21071 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
21072 "Unexpected type for custom-lowering FP_ROUND");
21074 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
21075 "With both FP DP and 16, any FP conversion is legal!");
21080 if (SrcSz == 32 && Subtarget->hasFP16())
21085 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
21086 "Unexpected type for custom-lowering FP_ROUND");
21090 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
21102 if (v == 0xffffffff)
21114 bool ForCodeSize)
const {
21115 if (!Subtarget->hasVFP3Base())
21117 if (VT == MVT::f16 && Subtarget->hasFullFP16())
21119 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
21122 if (VT == MVT::f32)
21124 if (VT == MVT::f64 && Subtarget->hasFP64())
21137 case Intrinsic::arm_neon_vld1:
21138 case Intrinsic::arm_neon_vld2:
21139 case Intrinsic::arm_neon_vld3:
21140 case Intrinsic::arm_neon_vld4:
21141 case Intrinsic::arm_neon_vld2lane:
21142 case Intrinsic::arm_neon_vld3lane:
21143 case Intrinsic::arm_neon_vld4lane:
21144 case Intrinsic::arm_neon_vld2dup:
21145 case Intrinsic::arm_neon_vld3dup:
21146 case Intrinsic::arm_neon_vld4dup: {
21149 auto &
DL =
I.getDataLayout();
21150 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21152 Info.ptrVal =
I.getArgOperand(0);
21154 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21161 case Intrinsic::arm_neon_vld1x2:
21162 case Intrinsic::arm_neon_vld1x3:
21163 case Intrinsic::arm_neon_vld1x4: {
21166 auto &
DL =
I.getDataLayout();
21167 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21169 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
21171 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
21177 case Intrinsic::arm_neon_vst1:
21178 case Intrinsic::arm_neon_vst2:
21179 case Intrinsic::arm_neon_vst3:
21180 case Intrinsic::arm_neon_vst4:
21181 case Intrinsic::arm_neon_vst2lane:
21182 case Intrinsic::arm_neon_vst3lane:
21183 case Intrinsic::arm_neon_vst4lane: {
21186 auto &
DL =
I.getDataLayout();
21187 unsigned NumElts = 0;
21188 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21189 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21192 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21195 Info.ptrVal =
I.getArgOperand(0);
21197 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21204 case Intrinsic::arm_neon_vst1x2:
21205 case Intrinsic::arm_neon_vst1x3:
21206 case Intrinsic::arm_neon_vst1x4: {
21209 auto &
DL =
I.getDataLayout();
21210 unsigned NumElts = 0;
21211 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21212 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21215 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21218 Info.ptrVal =
I.getArgOperand(0);
21220 Info.align =
I.getParamAlign(0).valueOrOne();
21226 case Intrinsic::arm_mve_vld2q:
21227 case Intrinsic::arm_mve_vld4q: {
21231 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21233 Info.ptrVal =
I.getArgOperand(0);
21241 case Intrinsic::arm_mve_vst2q:
21242 case Intrinsic::arm_mve_vst4q: {
21245 Type *VecTy =
I.getArgOperand(1)->getType();
21246 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21248 Info.ptrVal =
I.getArgOperand(0);
21256 case Intrinsic::arm_mve_vldr_gather_base:
21257 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21259 Info.ptrVal =
nullptr;
21261 Info.align =
Align(1);
21266 case Intrinsic::arm_mve_vldr_gather_base_wb:
21267 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21269 Info.ptrVal =
nullptr;
21270 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21271 Info.align =
Align(1);
21276 case Intrinsic::arm_mve_vldr_gather_offset:
21277 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21279 Info.ptrVal =
nullptr;
21284 Info.align =
Align(1);
21289 case Intrinsic::arm_mve_vstr_scatter_base:
21290 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21292 Info.ptrVal =
nullptr;
21293 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21294 Info.align =
Align(1);
21299 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21300 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21302 Info.ptrVal =
nullptr;
21303 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21304 Info.align =
Align(1);
21309 case Intrinsic::arm_mve_vstr_scatter_offset:
21310 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21312 Info.ptrVal =
nullptr;
21317 Info.align =
Align(1);
21322 case Intrinsic::arm_ldaex:
21323 case Intrinsic::arm_ldrex: {
21324 auto &
DL =
I.getDataLayout();
21325 Type *ValTy =
I.getParamElementType(0);
21328 Info.ptrVal =
I.getArgOperand(0);
21330 Info.align =
DL.getABITypeAlign(ValTy);
21335 case Intrinsic::arm_stlex:
21336 case Intrinsic::arm_strex: {
21337 auto &
DL =
I.getDataLayout();
21338 Type *ValTy =
I.getParamElementType(1);
21341 Info.ptrVal =
I.getArgOperand(1);
21343 Info.align =
DL.getABITypeAlign(ValTy);
21348 case Intrinsic::arm_stlexd:
21349 case Intrinsic::arm_strexd:
21351 Info.memVT = MVT::i64;
21352 Info.ptrVal =
I.getArgOperand(2);
21354 Info.align =
Align(8);
21359 case Intrinsic::arm_ldaexd:
21360 case Intrinsic::arm_ldrexd:
21362 Info.memVT = MVT::i64;
21363 Info.ptrVal =
I.getArgOperand(0);
21365 Info.align =
Align(8);
21379 assert(Ty->isIntegerTy());
21381 unsigned Bits = Ty->getPrimitiveSizeInBits();
21382 if (Bits == 0 || Bits > 32)
21388 unsigned Index)
const {
21398 if (!Subtarget->hasDataBarrier()) {
21402 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21403 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21404 Builder.getInt32(0), Builder.getInt32(7),
21405 Builder.getInt32(10), Builder.getInt32(5)};
21406 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
21416 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
21437 if (Subtarget->preferISHSTBarriers())
21470 bool has64BitAtomicStore;
21471 if (Subtarget->isMClass())
21472 has64BitAtomicStore =
false;
21473 else if (Subtarget->isThumb())
21474 has64BitAtomicStore = Subtarget->hasV7Ops();
21476 has64BitAtomicStore = Subtarget->hasV6Ops();
21478 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21492 bool has64BitAtomicLoad;
21493 if (Subtarget->isMClass())
21494 has64BitAtomicLoad =
false;
21495 else if (Subtarget->isThumb())
21496 has64BitAtomicLoad = Subtarget->hasV7Ops();
21498 has64BitAtomicLoad = Subtarget->hasV6Ops();
21514 if (Subtarget->isMClass())
21515 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21516 else if (Subtarget->isThumb())
21517 hasAtomicRMW = Subtarget->hasV7Ops();
21519 hasAtomicRMW = Subtarget->hasV6Ops();
21520 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21544 bool HasAtomicCmpXchg;
21545 if (Subtarget->isMClass())
21546 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21547 else if (Subtarget->isThumb())
21548 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21550 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21552 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21559 return InsertFencesForAtomic;
21564 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21570 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21571 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21573 RTLIB::LibcallImpl SecurityCookieVar =
21574 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21575 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21576 SecurityCookieVar != RTLIB::Unsupported) {
21587 F->addParamAttr(0, Attribute::AttrKind::InReg);
21594 unsigned &
Cost)
const {
21596 if (!Subtarget->hasNEON())
21625 unsigned Opcode =
Op.getOpcode();
21627 case ARMISD::VORRIMM:
21628 case ARMISD::VBICIMM:
21632 Op, DemandedElts, DAG, Kind, ConsiderFlags,
Depth);
21636 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21640 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21645 if (!Subtarget->hasV7Ops())
21651 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21653 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21661 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21670 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21676 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21678 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21681 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21683 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21684 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21685 if (!Subtarget->isLittle())
21687 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21688 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21689 return Builder.CreateOr(
21690 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21694 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21695 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21698 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21699 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21704 if (!Subtarget->hasV7Ops())
21706 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21712 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21720 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21724 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21725 if (!Subtarget->isLittle())
21727 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21730 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21734 CallInst *CI = Builder.CreateCall(
21735 Strex, {Builder.CreateZExtOrBitCast(
21745 return Subtarget->isMClass();
21753 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21760 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21763 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21771 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21779 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21782 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21787 if (Subtarget->hasNEON() && VecSize == 64)
21789 return VecSize % 128 == 0;
21793 if (Subtarget->hasNEON())
21795 if (Subtarget->hasMVEIntegerOps())
21815 "Invalid interleave factor");
21816 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21818 "Unmatched number of shufflevectors and indices");
21823 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21826 Type *EltTy = VecTy->getElementType();
21829 Align Alignment = LI->getAlign();
21847 Value *BaseAddr = LI->getPointerOperand();
21849 if (NumLoads > 1) {
21853 VecTy->getNumElements() / NumLoads);
21859 if (Subtarget->hasNEON()) {
21860 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21861 Type *Tys[] = {VecTy, PtrTy};
21862 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21863 Intrinsic::arm_neon_vld3,
21864 Intrinsic::arm_neon_vld4};
21867 Ops.push_back(BaseAddr);
21868 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21870 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21873 assert((Factor == 2 || Factor == 4) &&
21874 "expected interleave factor of 2 or 4 for MVE");
21876 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21877 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21878 Type *Tys[] = {VecTy, PtrTy};
21881 Ops.push_back(BaseAddr);
21882 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21892 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21896 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21897 VecTy->getNumElements() * Factor);
21903 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21905 unsigned Index = Indices[i];
21907 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21911 SubVec = Builder.CreateIntToPtr(
21915 SubVecs[SV].push_back(SubVec);
21924 auto &SubVec = SubVecs[SVI];
21927 SVI->replaceAllUsesWith(WideVec);
21963 const APInt &GapMask)
const {
21965 "Invalid interleave factor");
21970 "Unexpected mask on store");
21973 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21975 unsigned LaneLen = VecTy->getNumElements() / Factor;
21976 Type *EltTy = VecTy->getElementType();
21980 Align Alignment =
SI->getAlign();
21997 Type *IntTy =
DL.getIntPtrType(EltTy);
22002 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
22003 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
22009 Value *BaseAddr =
SI->getPointerOperand();
22011 if (NumStores > 1) {
22014 LaneLen /= NumStores;
22024 if (Subtarget->hasNEON()) {
22025 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
22026 Intrinsic::arm_neon_vst3,
22027 Intrinsic::arm_neon_vst4};
22028 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22029 Type *Tys[] = {PtrTy, SubVecTy};
22032 Ops.push_back(BaseAddr);
22034 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
22035 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
22037 assert((Factor == 2 || Factor == 4) &&
22038 "expected interleave factor of 2 or 4 for MVE");
22040 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
22041 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
22042 Type *Tys[] = {PtrTy, SubVecTy};
22045 Ops.push_back(BaseAddr);
22047 for (
unsigned F = 0;
F < Factor;
F++) {
22048 Ops.push_back(Builder.getInt32(
F));
22049 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
22055 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
22058 if (StoreCount > 0)
22059 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
22060 BaseAddr, LaneLen * Factor);
22065 for (
unsigned i = 0; i < Factor; i++) {
22066 unsigned IdxI = StoreCount * LaneLen * Factor + i;
22067 if (Mask[IdxI] >= 0) {
22068 Shuffles.
push_back(Builder.CreateShuffleVector(
22071 unsigned StartMask = 0;
22072 for (
unsigned j = 1; j < LaneLen; j++) {
22073 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
22074 if (Mask[IdxJ * Factor + IdxI] >= 0) {
22075 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
22085 Shuffles.
push_back(Builder.CreateShuffleVector(
22106 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
22110 Members += SubMembers;
22116 Members += SubMembers * AT->getNumElements();
22117 }
else if (Ty->isFloatTy()) {
22122 }
else if (Ty->isDoubleTy()) {
22134 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
22136 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
22138 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
22151 return (Members > 0 && Members <= 4);
22157 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
22159 return ABITypeAlign;
22164 assert(StackAlign &&
"data layout string is missing stack alignment");
22165 return std::min(ABITypeAlign, *StackAlign);
22174 if (getEffectiveCallingConv(CallConv, isVarArg) !=
22183 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
22184 return IsHA || IsIntArray;
22188 const Constant *PersonalityFn)
const {
22196 const Constant *PersonalityFn)
const {
22209void ARMTargetLowering::insertCopiesSplitCSR(
22213 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22223 RC = &ARM::GPRRegClass;
22224 else if (ARM::DPRRegClass.
contains(*
I))
22225 RC = &ARM::DPRRegClass;
22235 assert(Entry->getParent()->getFunction().hasFnAttribute(
22236 Attribute::NoUnwind) &&
22237 "Function should be nounwind in insertCopiesSplitCSR!");
22238 Entry->addLiveIn(*
I);
22243 for (
auto *Exit : Exits)
22245 TII->get(TargetOpcode::COPY), *
I)
22256 return Subtarget->hasMVEIntegerOps();
22266 unsigned NumElements = VTy->getNumElements();
22273 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22274 return Subtarget->hasMVEFloatOps();
22279 return Subtarget->hasMVEIntegerOps() &&
22280 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22281 ScalarTy->isIntegerTy(32));
22285 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22296 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22298 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22300 if (TyWidth > 128) {
22301 int Stride = Ty->getNumElements() / 2;
22305 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22307 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22308 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22309 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22310 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22311 Value *LowerSplitAcc =
nullptr;
22312 Value *UpperSplitAcc =
nullptr;
22315 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22316 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22320 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22322 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22324 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22325 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22332 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22335 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22337 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22338 {ConstRotation, InputB, InputA});
22343 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22346 ConstRotation = ConstantInt::get(IntTy, 0);
22348 ConstRotation = ConstantInt::get(IntTy, 1);
22350 if (!ConstRotation)
22353 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22354 {ConstHalving, ConstRotation, InputA, InputB});
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static SDValue carryFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG, bool Invert)
static SDValue overflowFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue valueToCarryFlag(SDValue Value, SelectionDAG &DAG, bool Invert)
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static bool optimizeLogicalImm(SDValue Op, unsigned Size, uint64_t Imm, const APInt &Demanded, TargetLowering::TargetLoweringOpt &TLO, unsigned NewOpc)
static bool isSafeSignedCMN(SDValue Op, SelectionDAG &DAG)
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static SDValue matchCSET(unsigned &Opcode, bool &InvertCond, SDValue TrueVal, SDValue FalseVal, const ARMSubtarget *Subtarget)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getInvertedARMCondCode(SDValue ARMcc, SelectionDAG &DAG)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static SDValue LowerADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG, unsigned Opcode, bool IsSigned)
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static int getNegationCost(SDValue Op)
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static bool isLegalLogicalImmediate(unsigned Imm, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static unsigned SelectPairHalf(unsigned Elements, ArrayRef< int > Mask, unsigned Index)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerTruncate(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformHWLoopCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformORCombineToShiftInsert(SelectionDAG &DAG, SDValue AndOp, SDValue ShiftOp, EVT VT, SDLoc dl)
static SDValue PerformSplittingMVETruncToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool isVUZP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of "vector_shuffle v,...
static bool isHomogeneousAggregate(Type *Ty, HABaseType &Base, uint64_t &Members)
static SDValue PerformMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformFADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerReverse_VECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
static SDValue PerformANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDVecReduce(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerPredicateStore(SDValue Op, SelectionDAG &DAG)
static SDValue SearchLoopIntrinsic(SDValue N, ISD::CondCode &CC, int &Imm, bool &Negate)
static bool canChangeToInt(SDValue Op, bool &SeenZero, const ARMSubtarget *Subtarget)
canChangeToInt - Given the fp compare operand, return true if it is suitable to morph to an integer c...
static unsigned getStOpcode(unsigned StSize, bool IsThumb1, bool IsThumb2)
Return the store opcode for a given store size.
static bool IsVUZPShuffleNode(SDNode *N)
static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddCombineTo64BitSMLAL16(SDNode *AddcNode, SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void attachMEMCPYScratchRegs(const ARMSubtarget *Subtarget, MachineInstr &MI, const SDNode *Node)
Attaches vregs to MEMCPY that it will use as scratch registers when it is expanded into LDM/STM.
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
static SDValue findMUL_LOHI(SDValue V)
static SDValue LowerVECTOR_SHUFFLE_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformORCombine_i1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformSplittingMVEEXTToWideningLoad(SDNode *N, SelectionDAG &DAG)
static SDValue PerformSplittingToWideningLoad(SDNode *N, SelectionDAG &DAG)
static void genTPLoopBody(MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpEntry, MachineBasicBlock *TpExit, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI, Register OpSrcReg, Register OpDestReg, Register ElementCountReg, Register TotalIterationsReg, bool IsMemcpy)
Adds logic in the loopBody MBB to generate MVE_VCTP, t2DoLoopDec and t2DoLoopEnd.
static SDValue PerformBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformBUILD_VECTORCombine - Target-specific dag combine xforms for ISD::BUILD_VECTOR.
static SDValue LowerVecReduceF(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformMinMaxCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformMinMaxCombine - Target-specific DAG combining for creating truncating saturates.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis false
Function Alias Analysis Results
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static constexpr roundingMode rmTowardZero
LLVM_ABI bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
unsigned logBase2() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
const ARMBaseRegisterInfo & getRegisterInfo() const
const uint32_t * getSjLjDispatchPreservedMask(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const uint32_t * getTLSCallPreservedMask(const MachineFunction &MF) const
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
int getVarArgsFrameIndex() const
int getPromotedConstpoolIncrease() const
SmallPtrSet< const GlobalVariable *, 2 > & getGlobalsPromotedToConstantPool()
void setArgumentStackToRestore(unsigned v)
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
void setPromotedConstpoolIncrease(int Sz)
bool isThumb1OnlyFunction() const
void setArgRegsSaveSize(unsigned s)
bool isCmseNSEntryFunction() const
void setReturnRegsCount(unsigned s)
void setVarArgsFrameIndex(int Index)
unsigned getArgRegsSaveSize() const
void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV)
Indicate to the backend that GV has had its storage changed to inside a constant pool.
void setIsSplitCSR(bool s)
void setArgumentStackSize(unsigned size)
unsigned getArgumentStackSize() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
const ARMTargetLowering * getTargetLowering() const override
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool isReadOnly(const GlobalValue *GV) const
unsigned getMaxSupportedInterleaveFactor() const override
Get the maximum supported factor for interleaved memory accesses.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
unsigned getNumInterleavedAccesses(VectorType *VecTy, const DataLayout &DL) const
Returns the number of interleaved accesses that will be generated when lowering accesses of the given...
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Align getABIAlignmentForCallingConv(Type *ArgTy, const DataLayout &DL) const override
Return the correct alignment for the current calling convention.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
const ARMSubtarget * getSubtarget() const
bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const
bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const
Returns true if the addressing mode representing by AM is legal for the Thumb1 target,...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
bool isFNegFree(EVT VT) const override
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
bool shouldFoldConstantShiftPairToMask(const SDNode *N) const override
Return true if it is profitable to fold a pair of shifts into a mask.
bool isDesirableToCommuteXorWithShift(const SDNode *N) const override
Return true if it is profitable to combine an XOR of a logical shift to create a logical shift of NOT...
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const
PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
Value * createComplexDeinterleavingIR(IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, Value *Accumulator=nullptr) const override
Create the IR node for the given complex deinterleaving operation.
bool isComplexDeinterleavingSupported() const override
Does this target support complex deinterleaving.
SDValue PerformMVEExtCombine(SDNode *N, DAGCombinerInfo &DCI) const
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const override
Inserts necessary declarations for SSP (stack protection) purpose.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &OriginalDemandedBits, const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the value type to use for ISD::SETCC.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const override
Perform a store-conditional operation to Addr.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool isVarArg) const
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for this result type with this index.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
isShuffleMaskLegal - Targets can use this to indicate that they only support some VECTOR_SHUFFLE oper...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
bool lowerInterleavedStore(Instruction *Store, Value *Mask, ShuffleVectorInst *SVI, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved store into a vstN intrinsic.
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
bool useLoadStackGuardNode(const Module &M) const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vldN intrinsic.
std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override
Return the largest legal super-reg register class of the register class for the specified type and it...
bool preferSelectsOverBooleanArithmetic(EVT VT) const override
Should we prefer selects to doing arithmetic on boolean types.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
bool supportKCFIBundles() const override
Return true if the target supports kcfi operand bundles.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool isVarArg) const
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
allowsMisalignedMemoryAccesses - Returns true if the target allows unaligned memory accesses of the s...
bool isLegalInterleavedAccessType(unsigned Factor, FixedVectorType *VecTy, Align Alignment, const DataLayout &DL) const
Returns true if VecTy is a legal interleaved access type.
bool isVectorLoadExtDesirable(SDValue ExtVal) const override
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, unsigned &Cost) const override
Return true if the target can combine store(extractelement VectorTy,Idx).
bool useSoftFloat() const override
bool alignLoopsWithOptSize() const override
Should loops be aligned even when the function is marked OptSize (but not MinSize).
SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const
bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override
Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail ...
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
bool hasAndNotCompare(SDValue V) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
bool isFloatingPointOperation() const
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
The address of a basic block.
static BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
LLVM_ABI int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, uint32_t BitWidth) const
If this is a constant FP splat and the splatted constant FP is an exact power or 2,...
CCState - This class holds information needed while lowering arguments and return values.
void getInRegsParamInfo(unsigned InRegsParamRecordIndex, unsigned &BeginReg, unsigned &EndReg) const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
void rewindByValRegsInfo()
unsigned getInRegsParamsProcessed() const
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd)
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
unsigned getInRegsParamsCount() const
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
const APFloat & getValueAPF() const
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
MachineConstantPoolValue * getMachineCPVal() const
bool isMachineConstantPoolEntry() const
const Constant * getConstVal() const
LLVM_ABI Type * getType() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
MaybeAlign getStackAlignment() const
Returns the natural stack alignment, or MaybeAlign() if one wasn't specified.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
StringRef getInternalSymbolPrefix() const
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
static bool isWeakForLinker(LinkageTypes Linkage)
Whether the definition of this global may be replaced at link time.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
Tracks which library functions to use for a particular subtarget.
CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const
Get the CallingConv that should be used for the specified libcall.
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Describe properties that are true of each instruction in the target description file.
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
bool is64BitVector() const
Return true if this is a 64-bit vector type.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI unsigned createJumpTableIndex(const std::vector< MachineBasicBlock * > &DestBBs)
createJumpTableIndex - Create a new jump table.
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
This class is used to represent an MLOAD node.
This class is used to represent an MSTORE node.
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
const LibcallLoweringInfo & getLibcalls() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
This instruction constructs a fixed permutation of two input vectors.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
Represent a constant reference to a string, i.e.
const unsigned char * bytes_end() const
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
const unsigned char * bytes_begin() const
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
Provides information about what library functions are available for the current target.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
ShiftLegalizationStrategy
Return the preferred strategy to legalize tihs SHIFT instruction, with ExpansionFactor being the recu...
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
const TargetMachine & getTargetMachine() const
virtual void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const
Inserts necessary declarations for SSP (stack protection) purpose.
void setIndexedMaskedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked load does or does not work with the specified type and ind...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
virtual unsigned getMaxSupportedInterleaveFactor() const
Get the maximum supported factor for interleaved memory accesses.
void setIndexedMaskedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action)
Indicate that the specified indexed masked store does or does not work with the specified type and in...
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Get the libcall impl routine name for the specified libcall.
static StringRef getLibcallImplName(RTLIB::LibcallImpl Call)
Get the libcall routine name for the specified libcall implementation.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool expandDIVREMByConstant(SDNode *N, SmallVectorImpl< SDValue > &Result, EVT HiLoVT, SelectionDAG &DAG, SDValue LL=SDValue(), SDValue LH=SDValue()) const
Attempt to expand an n-bit div/rem/divrem by constant using an n/2-bit algorithm.
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual ArrayRef< MCPhysReg > getRoundingControlRegisters() const
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, UndefPoisonKind Kind, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
void setTypeIdForCallsiteInfo(const CallBase *CB, MachineFunction &MF, MachineFunction::CallSiteInfo &CSInfo) const
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
ExceptionHandling getExceptionModel() const
Return the ExceptionHandling to use, considering TargetOptions and the Triple's default.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
bool isOSWindows() const
Tests whether the OS is Windows.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
Base class of all SIMD vector types.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static CondCodes getOppositeCondition(CondCodes CC)
@ SECREL
Thread Pointer Offset.
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
TOF
Target Operand Flag enum.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
static ShiftOpc getShiftOpcForNode(unsigned Opcode)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits)
decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the element value and the element ...
unsigned getAM2Offset(unsigned AM2Opc)
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
unsigned createVMOVModImm(unsigned OpCmode, unsigned Val)
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
int getFP32FP16Imm(const APInt &Imm)
If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding for it.
AddrOpc getAM2Op(unsigned AM2Opc)
bool isBitFieldInvertedMask(unsigned v)
const unsigned FPStatusBits
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
const unsigned FPReservedBits
const unsigned RoundingBitsPos
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Swift
Calling convention for Swift.
@ ARM_APCS
ARM Procedure Calling Standard (obsolete, but still used on some targets).
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ ARM_AAPCS
ARM Architecture Procedure Calling Standard calling convention (aka EABI).
@ CXX_FAST_TLS
Used for access functions.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ ARM_AAPCS_VFP
Same as ARM_AAPCS, but uses hard floating point ABI.
@ C
The default llvm calling convention, compatible with C.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ SET_FPENV
Sets the current floating-point environment.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
@ FGETSIGN
INT = FGETSIGN(FP) - Return the sign bit of the specified floating point value as an integer 0/1 valu...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ RESET_FPENV
Set floating-point environment to default state.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SET_FPMODE
Sets the current dynamic floating-point control modes.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ EH_SJLJ_SETUP_DISPATCH
OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) The target initializes the dispatch table here.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ RESET_FPMODE
Sets default dynamic floating-point control modes.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ BR
Control flow instructions. These all have token chains.
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ BR_JT
BR_JT - Jumptable branch.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SMULO
Same for multiplication.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ SADDO_CARRY
Carry-using overflow-aware nodes for multiple precision addition and subtraction.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ SjLj
setjmp/longjmp based exceptions
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
FunctionAddr VTableAddr uintptr_t uintptr_t Data
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
UndefPoisonKind
Enumeration to track whether we are interested in Undef, Poison, or both.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
bool isUnknown() const
Returns true if we don't know any bits.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
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.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)