83#include "llvm/IR/IntrinsicsARM.h"
118#define DEBUG_TYPE "arm-isel"
121STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
122STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
124 "Number of constants with their storage promoted into constant pools");
128 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
133 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
138 cl::desc(
"Maximum size of constant to promote into a constant pool"),
142 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
147 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
152 cl::desc(
"Maximum number of base-updates to check generating postindex."),
160 ARM::R0, ARM::R1, ARM::R2, ARM::R3
174void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
175 if (VT != PromotedLdStVT) {
184 if (ElemTy != MVT::f64)
188 if (ElemTy == MVT::i32) {
232void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
234 addTypeForNEON(VT, MVT::f64);
237void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
239 addTypeForNEON(VT, MVT::v2f64);
242void ARMTargetLowering::setAllExpand(
MVT VT) {
255void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
262void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
263 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
265 for (
auto VT : IntTypes) {
340 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
341 for (
auto VT : FloatTypes) {
415 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
416 for (
auto VT : LongTypes) {
433 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
434 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
435 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
452 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
461 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
462 for (
auto VT : pTypes) {
513 RegInfo(Subtarget->getRegisterInfo()),
514 Itins(Subtarget->getInstrItineraryData()) {
520 const Triple &TT = TM.getTargetTriple();
522 if (Subtarget->isThumb1Only())
527 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
528 Subtarget->hasFPRegs()) {
537 if (!Subtarget->hasVFP2Base()) {
538 setAllExpand(MVT::f32);
544 if (!Subtarget->hasFP64()) {
545 setAllExpand(MVT::f64);
555 if (Subtarget->hasFullFP16()) {
570 if (Subtarget->hasBF16()) {
572 setAllExpand(MVT::bf16);
573 if (!Subtarget->hasFullFP16())
585 addAllExtLoads(VT, InnerVT,
Expand);
594 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
597 if (!Subtarget->hasV8_1MMainlineOps())
600 if (!Subtarget->isThumb1Only())
609 if (Subtarget->hasMVEIntegerOps())
610 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
613 if (Subtarget->hasLOB()) {
617 if (Subtarget->hasNEON()) {
618 addDRTypeForNEON(MVT::v2f32);
619 addDRTypeForNEON(MVT::v8i8);
620 addDRTypeForNEON(MVT::v4i16);
621 addDRTypeForNEON(MVT::v2i32);
622 addDRTypeForNEON(MVT::v1i64);
624 addQRTypeForNEON(MVT::v4f32);
625 addQRTypeForNEON(MVT::v2f64);
626 addQRTypeForNEON(MVT::v16i8);
627 addQRTypeForNEON(MVT::v8i16);
628 addQRTypeForNEON(MVT::v4i32);
629 addQRTypeForNEON(MVT::v2i64);
631 if (Subtarget->hasFullFP16()) {
632 addQRTypeForNEON(MVT::v8f16);
633 addDRTypeForNEON(MVT::v4f16);
636 if (Subtarget->hasBF16()) {
637 addQRTypeForNEON(MVT::v8bf16);
638 addDRTypeForNEON(MVT::v4bf16);
642 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
682 if (Subtarget->hasNEON()) {
795 if (!Subtarget->hasVFP4Base()) {
804 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
813 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
822 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
830 if (Subtarget->hasMVEIntegerOps()) {
835 if (Subtarget->hasMVEFloatOps()) {
839 if (!Subtarget->hasFP64()) {
885 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
888 if (Subtarget->hasFullFP16()) {
896 if (!Subtarget->hasFP16()) {
925 if (!Subtarget->isThumb1Only()) {
944 if (TT.isTargetAEABI() && !Subtarget->allowsUnalignedMem()) {
956 if (!Subtarget->isThumb1Only()) {
963 if (Subtarget->hasDSP()) {
973 if (Subtarget->hasBaseDSP()) {
981 if (Subtarget->isThumb1Only()) {
985 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
986 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1001 if (Subtarget->hasMVEIntegerOps())
1005 if (Subtarget->isThumb1Only()) {
1011 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1025 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1034 if (Subtarget->hasPerfMon())
1038 if (!Subtarget->hasV6Ops())
1041 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1042 : Subtarget->hasDivideInARMMode();
1049 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1061 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1062 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1065 HasStandaloneRem =
false;
1092 if (TT.isOSWindows())
1099 InsertFencesForAtomic =
false;
1100 if (Subtarget->hasAnyDataBarrier() &&
1101 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1105 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1110 if (!Subtarget->hasAcquireRelease() ||
1113 InsertFencesForAtomic =
true;
1119 if (Subtarget->hasDataBarrier())
1120 InsertFencesForAtomic =
true;
1140 if (!InsertFencesForAtomic) {
1147 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1159 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1160 Subtarget->hasForced32BitAtomics()) {
1174 if (!Subtarget->hasV6Ops()) {
1180 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1181 !Subtarget->isThumb1Only()) {
1210 if (Subtarget->hasFullFP16()) {
1220 if (Subtarget->hasFullFP16())
1235 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1236 !Subtarget->isThumb1Only()) {
1243 if (!Subtarget->hasVFP4Base()) {
1249 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1251 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1259 if (!Subtarget->hasFP16()) {
1279 if (Subtarget->hasFPARMv8Base()) {
1289 if (Subtarget->hasFP64())
1293 if (Subtarget->hasNEON()) {
1303 if (Subtarget->hasFullFP16()) {
1340 if (Subtarget->hasNEON()) {
1352 if (Subtarget->hasV8Ops()) {
1362 if (Subtarget->hasFullFP16()) {
1385 if (TT.isOSWindows()) {
1402 if (Subtarget->hasMVEIntegerOps())
1405 if (Subtarget->hasV6Ops())
1407 if (Subtarget->isThumb1Only())
1410 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1411 Subtarget->isThumb2()) {
1417 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1418 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1440 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1448 return Subtarget->useSoftFloat();
1452 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1465std::pair<const TargetRegisterClass *, uint8_t>
1476 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1477 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1478 RRC = &ARM::DPRRegClass;
1483 if (Subtarget->useNEONForSinglePrecisionFP())
1486 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1487 case MVT::v4f32:
case MVT::v2f64:
1488 RRC = &ARM::DPRRegClass;
1492 RRC = &ARM::DPRRegClass;
1496 RRC = &ARM::DPRRegClass;
1500 return std::make_pair(RRC,
Cost);
1509 if ((Subtarget->hasMVEIntegerOps() &&
1510 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1511 VT == MVT::v16i8)) ||
1512 (Subtarget->hasMVEFloatOps() &&
1513 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1527 if (Subtarget->hasNEON()) {
1528 if (VT == MVT::v4i64)
1529 return &ARM::QQPRRegClass;
1530 if (VT == MVT::v8i64)
1531 return &ARM::QQQQPRRegClass;
1533 if (Subtarget->hasMVEIntegerOps()) {
1534 if (VT == MVT::v4i64)
1535 return &ARM::MQQPRRegClass;
1536 if (VT == MVT::v8i64)
1537 return &ARM::MQQQQPRRegClass;
1546 Align &PrefAlign)
const {
1553 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1565 unsigned NumVals =
N->getNumValues();
1569 for (
unsigned i = 0; i != NumVals; ++i) {
1570 EVT VT =
N->getValueType(i);
1571 if (VT == MVT::Glue || VT == MVT::Other)
1577 if (!
N->isMachineOpcode())
1585 if (
MCID.getNumDefs() == 0)
1587 if (!Itins->isEmpty() &&
1588 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1602 return Const->getZExtValue() == 16;
1610 return Const->getZExtValue() == 16;
1618 return Const->getZExtValue() == 16;
1687 bool isVarArg)
const {
1706 if (!
getTM().isAAPCS_ABI())
1708 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1716 if (!
getTM().isAAPCS_ABI()) {
1717 if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() && !isVarArg)
1720 }
else if (Subtarget->hasVFP2Base() && !Subtarget->isThumb1Only() &&
1729 bool isVarArg)
const {
1730 return CCAssignFnForNode(CC,
false, isVarArg);
1734 bool isVarArg)
const {
1735 return CCAssignFnForNode(CC,
true, isVarArg);
1742 bool isVarArg)
const {
1743 switch (getEffectiveCallingConv(CC, isVarArg)) {
1769 if (Subtarget->hasFullFP16()) {
1770 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1782 if (Subtarget->hasFullFP16()) {
1783 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1796SDValue ARMTargetLowering::LowerCallResult(
1800 SDValue ThisVal,
bool isCmseNSCall)
const {
1808 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1809 CCValAssign VA = RVLocs[i];
1813 if (i == 0 && isThisReturn) {
1815 "unexpected return calling convention register assignment");
1833 if (!Subtarget->isLittle())
1835 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1850 if (!Subtarget->isLittle())
1852 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1882 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1893std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1895 bool IsTailCall,
int SPDiff)
const {
1897 MachinePointerInfo DstInfo;
1917 return std::make_pair(DstAddr, DstInfo);
1926ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1939 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1942 int SrcFI = SrcFrameIdxNode->getIndex();
1943 int DstFI = DstFrameIdxNode->getIndex();
1945 "byval passed in non-fixed stack slot");
1967 if (SrcOffset == DstOffset)
1975 RegsToPassVector &RegsToPass,
1982 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1983 unsigned id = Subtarget->isLittle() ? 0 : 1;
1995 MachinePointerInfo DstInfo;
1996 std::tie(DstAddr, DstInfo) =
1997 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2014 SelectionDAG &DAG = CLI.
DAG;
2016 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2017 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2018 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2025 const CallBase *CB = CLI.
CB;
2028 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2030 MachineFunction::CallSiteInfo CSInfo;
2031 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2032 bool isThisReturn =
false;
2033 bool isCmseNSCall =
false;
2034 bool isSibCall =
false;
2035 bool PreferIndirect =
false;
2036 bool GuardWithBTI =
false;
2046 !Subtarget->noBTIAtReturnTwice())
2054 isCmseNSCall =
true;
2057 if (!Subtarget->supportsTailCall())
2073 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2074 count_if(GV->users(), [&BB](
const User *U) {
2075 return isa<Instruction>(U) &&
2076 cast<Instruction>(U)->getParent() == BB;
2083 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2097 "site marked musttail");
2100 unsigned NumBytes = CCInfo.getStackSize();
2109 if (isTailCall && !isSibCall) {
2110 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2111 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2116 assert(StackAlign &&
"data layout string is missing stack alignment");
2117 NumBytes =
alignTo(NumBytes, *StackAlign);
2122 SPDiff = NumReusableBytes - NumBytes;
2126 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2142 RegsToPassVector RegsToPass;
2151 DenseMap<unsigned, SDValue> ByValTemporaries;
2155 for (
const CCValAssign &VA : ArgLocs) {
2157 SDValue Src = OutVals[ArgIdx];
2158 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2160 if (!
Flags.isByVal())
2164 MachinePointerInfo DstInfo;
2165 std::tie(Dst, DstInfo) =
2166 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2167 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2169 if (Copy == NoCopy) {
2174 }
else if (Copy == CopyOnce) {
2178 ByValTemporaries[ArgIdx] = Src;
2180 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2184 int TempFrameIdx = MFI.CreateStackObject(
2185 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2193 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2194 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2196 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2197 ByValTemporaries[ArgIdx] = Temp;
2200 if (!ByValCopyChains.
empty())
2210 bool AfterFormalArgLoads =
false;
2214 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2216 ++i, ++realArgIdx) {
2217 CCValAssign &VA = ArgLocs[i];
2218 SDValue Arg = OutVals[realArgIdx];
2219 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2220 bool isByVal =
Flags.isByVal();
2240 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2242 if (ByValTempChain) {
2247 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2248 if (Outs[
I].
Flags.isByVal())
2256 FrameIndexSDNode *FIN =
2261 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2264 for (
const CCValAssign &VA : ArgLocs) {
2272 if (!IncomingLoad.
empty()) {
2280 AfterFormalArgLoads =
true;
2292 auto ArgVT = Outs[realArgIdx].ArgVT;
2293 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2311 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2312 StackPtr, MemOpChains, isTailCall, SPDiff);
2316 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2317 StackPtr, MemOpChains, isTailCall, SPDiff);
2321 MachinePointerInfo DstInfo;
2322 std::tie(DstAddr, DstInfo) =
2323 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2327 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2328 StackPtr, MemOpChains, isTailCall, SPDiff);
2330 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2331 Outs[0].VT == MVT::i32) {
2333 "unexpected calling convention register assignment");
2335 "unexpected use of 'returned'");
2336 isThisReturn =
true;
2341 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2342 }
else if (isByVal) {
2344 unsigned offset = 0;
2348 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2349 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2352 bool NeedsStackCopy;
2353 if (
auto It = ByValTemporaries.
find(realArgIdx);
2354 It != ByValTemporaries.
end()) {
2355 ByValSrc = It->second;
2356 NeedsStackCopy =
true;
2359 NeedsStackCopy = !isTailCall;
2363 if (CurByValIdx < ByValArgsCount) {
2364 unsigned RegBegin, RegEnd;
2365 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2369 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2373 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2376 RegsToPass.push_back(std::make_pair(j, Load));
2381 offset = RegEnd - RegBegin;
2383 CCInfo.nextInRegsParam();
2388 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2391 MachinePointerInfo DstInfo;
2392 std::tie(Dst, DstInfo) =
2393 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2401 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2402 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2409 MachinePointerInfo DstInfo;
2410 std::tie(DstAddr, DstInfo) =
2411 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2418 if (!MemOpChains.
empty())
2424 for (
const auto &[
Reg,
N] : RegsToPass) {
2432 bool isDirect =
false;
2435 const Triple &
TT = TM.getTargetTriple();
2436 const GlobalValue *GVal =
nullptr;
2438 GVal =
G->getGlobal();
2439 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2441 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2442 bool isLocalARMFunc =
false;
2445 if (Subtarget->genLongCalls()) {
2447 "long-calls codegen is not position independent!");
2452 if (Subtarget->genExecuteOnly()) {
2453 if (Subtarget->useMovt())
2465 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2471 const char *Sym = S->getSymbol();
2473 if (Subtarget->genExecuteOnly()) {
2474 if (Subtarget->useMovt())
2486 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2493 if (!PreferIndirect) {
2498 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2500 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2501 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2503 ARMISD::WrapperPIC, dl, PtrVt,
2510 }
else if (Subtarget->isTargetCOFF()) {
2511 assert(Subtarget->isTargetWindows() &&
2512 "Windows is the only supported COFF target");
2516 else if (!TM.shouldAssumeDSOLocal(GVal))
2523 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2532 const char *Sym = S->getSymbol();
2533 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2535 ARMConstantPoolValue *CPV =
2537 ARMPCLabelIndex, 4);
2539 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2544 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2551 assert(!isARMFunc && !isDirect &&
2552 "Cannot handle call to ARM function or direct call");
2556 "call to non-secure function would require "
2557 "passing arguments on stack",
2563 "call to non-secure function would return value through pointer",
2570 if (Subtarget->isThumb()) {
2572 CallOpc = ARMISD::t2CALL_BTI;
2573 else if (isCmseNSCall)
2574 CallOpc = ARMISD::tSECALL;
2575 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2576 CallOpc = ARMISD::CALL_NOLINK;
2578 CallOpc = ARMISD::CALL;
2580 if (!isDirect && !Subtarget->hasV5TOps())
2581 CallOpc = ARMISD::CALL_NOLINK;
2582 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2584 !Subtarget->hasMinSize())
2586 CallOpc = ARMISD::CALL_NOLINK;
2588 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2595 if (isTailCall && !isSibCall) {
2600 std::vector<SDValue>
Ops;
2601 Ops.push_back(Chain);
2602 Ops.push_back(Callee);
2610 for (
const auto &[
Reg,
N] : RegsToPass)
2614 const uint32_t *
Mask;
2615 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2623 isThisReturn =
false;
2629 assert(Mask &&
"Missing call preserved mask for calling convention");
2633 Ops.push_back(InGlue);
2646 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2657 uint64_t CalleePopBytes =
2660 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2666 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2667 InVals, isThisReturn,
2668 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2675void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2676 Align Alignment)
const {
2678 Alignment = std::max(Alignment,
Align(4));
2684 unsigned AlignInRegs = Alignment.
value() / 4;
2685 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2686 for (
unsigned i = 0; i < Waste; ++i)
2692 unsigned Excess = 4 * (ARM::R4 -
Reg);
2699 if (NSAAOffset != 0 &&
Size > Excess) {
2711 unsigned ByValRegBegin =
Reg;
2712 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2716 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2722 Size = std::max<int>(
Size - Excess, 0);
2730bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2736 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2737 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2738 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2739 const SelectionDAG &DAG = CLI.
DAG;
2744 assert(Subtarget->supportsTailCall());
2757 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2759 if (!(Subtarget->isThumb1Only() ||
2760 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2761 AddressRegisters.
insert(ARM::R12);
2762 for (
const CCValAssign &AL : ArgLocs)
2764 AddressRegisters.
erase(
AL.getLocReg());
2765 if (AddressRegisters.
empty()) {
2766 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2785 <<
" (guaranteed tail-call CC)\n");
2786 return CalleeCC == CallerCC;
2791 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2793 if (isCalleeStructRet != isCallerStructRet) {
2806 const GlobalValue *GV =
G->getGlobal();
2809 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2810 TT.isOSBinFormatMachO())) {
2819 getEffectiveCallingConv(CalleeCC, isVarArg),
2820 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
2827 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2828 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2829 if (CalleeCC != CallerCC) {
2830 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2831 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2840 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2850 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2869 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2878 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2891 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2894 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2898 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2903 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2925 bool isLittleEndian = Subtarget->isLittle();
2928 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2937 "secure entry function would return value through pointer",
2942 for (
unsigned i = 0, realRVLocIdx = 0;
2944 ++i, ++realRVLocIdx) {
2945 CCValAssign &VA = RVLocs[i];
2948 SDValue Arg = OutVals[realRVLocIdx];
2949 bool ReturnF16 =
false;
2951 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
2984 auto RetVT = Outs[realRVLocIdx].ArgVT;
3006 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3010 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3016 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3028 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3030 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3035 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3045 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3071 !Subtarget->isMClass()) {
3072 if (Subtarget->isThumb1Only())
3079 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3082bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3083 if (
N->getNumValues() != 1)
3085 if (!
N->hasNUsesOfValue(1, 0))
3089 SDNode *
Copy = *
N->user_begin();
3093 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3095 TCChain =
Copy->getOperand(0);
3096 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3097 SDNode *VMov =
Copy;
3099 SmallPtrSet<SDNode*, 2>
Copies;
3100 for (SDNode *U : VMov->
users()) {
3108 for (SDNode *U : VMov->
users()) {
3109 SDValue UseChain =
U->getOperand(0);
3117 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3125 if (!
Copy->hasOneUse())
3132 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3134 TCChain =
Copy->getOperand(0);
3139 bool HasRet =
false;
3140 for (
const SDNode *U :
Copy->users()) {
3141 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3142 U->getOpcode() != ARMISD::INTRET_GLUE)
3154bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3155 if (!Subtarget->supportsTailCall())
3172 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3188 EVT PtrVT =
Op.getValueType();
3198 if (Subtarget->genExecuteOnly()) {
3203 auto GV =
new GlobalVariable(
3211 return LowerGlobalAddress(GA, DAG);
3217 if (Subtarget->isThumb1Only())
3218 CPAlign = std::max(CPAlign,
Align(4));
3224 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3231 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3240 unsigned ARMPCLabelIndex = 0;
3246 if (!IsPositionIndependent) {
3249 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3256 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3260 if (!IsPositionIndependent)
3263 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3291ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3294 "This function expects a Darwin target");
3299 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3305 MVT::i32,
DL, Chain, DescAddr,
3320 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3329 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3335ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3338 "Windows specific TLS lowering");
3362 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3370 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3371 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3377 MachinePointerInfo());
3384 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3397 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3399 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3401 ARMConstantPoolValue *CPV =
3412 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3419 TargetLowering::CallLoweringInfo CLI(DAG);
3424 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3425 return CallResult.first;
3434 const GlobalValue *GV = GA->
getGlobal();
3440 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3444 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3447 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3448 ARMConstantPoolValue *CPV =
3455 PtrVT, dl, Chain,
Offset,
3463 PtrVT, dl, Chain,
Offset,
3468 ARMConstantPoolValue *CPV =
3473 PtrVT, dl, Chain,
Offset,
3489 if (
TT.isOSDarwin())
3490 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3492 if (
TT.isOSWindows())
3493 return LowerGlobalTLSAddressWindows(
Op, DAG);
3496 assert(
TT.isOSBinFormatELF() &&
"Only ELF implemented here");
3502 return LowerToTLSGeneralDynamicModel(GA, DAG);
3505 return LowerToTLSExecModels(GA, DAG, model);
3514 while (!Worklist.
empty()) {
3522 if (!
I ||
I->getParent()->getParent() !=
F)
3551 if (!GVar || !GVar->hasInitializer() ||
3552 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3553 !GVar->hasLocalLinkage())
3558 auto *
Init = GVar->getInitializer();
3560 Init->needsDynamicRelocation())
3572 unsigned RequiredPadding = 4 - (
Size % 4);
3573 bool PaddingPossible =
3574 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3579 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3603 if (RequiredPadding != 4) {
3608 while (RequiredPadding--)
3620 ++NumConstpoolPromoted;
3621 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3626 if (!(GV = GA->getAliaseeObject()))
3629 return V->isConstant();
3638 return LowerGlobalAddressWindows(
Op, DAG);
3640 return LowerGlobalAddressELF(
Op, DAG);
3642 return LowerGlobalAddressDarwin(
Op, DAG);
3654 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3667 }
else if (Subtarget->isROPI() && IsRO) {
3672 }
else if (Subtarget->isRWPI() && !IsRO) {
3675 if (Subtarget->useMovt()) {
3678 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3680 ARMConstantPoolValue *CPV =
3683 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3697 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3698 if (Subtarget->useMovt())
3702 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3706 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3715 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3716 "ROPI/RWPI not currently supported for Darwin");
3721 if (Subtarget->useMovt())
3732 if (Subtarget->isGVIndirectSymbol(GV))
3741 "non-Windows COFF is not supported");
3742 assert(Subtarget->useMovt() &&
3743 "Windows on ARM expects to use movw/movt");
3744 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3745 "ROPI/RWPI not currently supported for Windows");
3752 else if (!TM.shouldAssumeDSOLocal(GV))
3775 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3776 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3777 Op.getOperand(1), Val);
3783 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3790 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3794SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3797 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3801 case Intrinsic::arm_gnu_eabi_mcount: {
3807 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3808 const uint32_t *
Mask =
3810 assert(Mask &&
"Missing call preserved mask for calling convention");
3815 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3819 if (Subtarget->isThumb())
3822 ARM::tBL_PUSHLR, dl, ResultTys,
3823 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3824 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3828 {ReturnAddress, Callee, RegisterMask, Chain}),
3837 unsigned IntNo =
Op.getConstantOperandVal(0);
3841 case Intrinsic::thread_pointer: {
3843 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3845 case Intrinsic::arm_cls: {
3849 const SDValue &Operand =
Op.getOperand(1);
3850 const EVT VTy =
Op.getValueType();
3853 case Intrinsic::arm_cls64: {
3859 case Intrinsic::arm_neon_vcls:
3860 case Intrinsic::arm_mve_vcls: {
3863 const EVT VTy =
Op.getValueType();
3866 case Intrinsic::eh_sjlj_lsda: {
3868 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3873 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3874 ARMConstantPoolValue *CPV =
3878 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3883 if (IsPositionIndependent) {
3885 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3889 case Intrinsic::arm_neon_vabs:
3892 case Intrinsic::arm_neon_vabds:
3893 if (
Op.getValueType().isInteger())
3895 Op.getOperand(1),
Op.getOperand(2));
3897 case Intrinsic::arm_neon_vabdu:
3899 Op.getOperand(1),
Op.getOperand(2));
3900 case Intrinsic::arm_neon_vmulls:
3901 case Intrinsic::arm_neon_vmullu: {
3902 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3903 ? ARMISD::VMULLs : ARMISD::VMULLu;
3904 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3905 Op.getOperand(1),
Op.getOperand(2));
3907 case Intrinsic::arm_neon_vminnm:
3908 case Intrinsic::arm_neon_vmaxnm: {
3909 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3911 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3912 Op.getOperand(1),
Op.getOperand(2));
3914 case Intrinsic::arm_neon_vminu:
3915 case Intrinsic::arm_neon_vmaxu: {
3916 if (
Op.getValueType().isFloatingPoint())
3918 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3920 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3921 Op.getOperand(1),
Op.getOperand(2));
3923 case Intrinsic::arm_neon_vmins:
3924 case Intrinsic::arm_neon_vmaxs: {
3926 if (!
Op.getValueType().isFloatingPoint()) {
3927 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3929 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3930 Op.getOperand(1),
Op.getOperand(2));
3932 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3934 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3935 Op.getOperand(1),
Op.getOperand(2));
3937 case Intrinsic::arm_neon_vtbl1:
3938 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
3939 Op.getOperand(1),
Op.getOperand(2));
3940 case Intrinsic::arm_neon_vtbl2:
3941 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
3942 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3943 case Intrinsic::arm_mve_pred_i2v:
3944 case Intrinsic::arm_mve_pred_v2i:
3945 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
3947 case Intrinsic::arm_mve_vreinterpretq:
3948 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
3950 case Intrinsic::arm_mve_lsll:
3951 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
3952 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3953 case Intrinsic::arm_mve_asrl:
3954 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
3955 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3956 case Intrinsic::arm_mve_vsli:
3957 return DAG.
getNode(ARMISD::VSLIIMM, SDLoc(
Op),
Op->getVTList(),
3958 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3959 case Intrinsic::arm_mve_vsri:
3960 return DAG.
getNode(ARMISD::VSRIIMM, SDLoc(
Op),
Op->getVTList(),
3961 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3972 if (!Subtarget->hasDataBarrier()) {
3976 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
3977 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
3978 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
3988 }
else if (Subtarget->preferISHSTBarriers() &&
3997 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4005 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4007 return Op.getOperand(0);
4010 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4012 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4014 return Op.getOperand(0);
4016 unsigned isData =
Op.getConstantOperandVal(4);
4017 if (Subtarget->isThumb()) {
4019 isRead = ~isRead & 1;
4020 isData = ~isData & 1;
4023 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4038 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4046 const SDLoc &dl)
const {
4048 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4050 const TargetRegisterClass *RC;
4052 RC = &ARM::tGPRRegClass;
4054 RC = &ARM::GPRRegClass;
4068 MVT::i32, dl, Root, FIN,
4074 if (!Subtarget->isLittle())
4076 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4089 const Value *OrigArg,
4090 unsigned InRegsParamRecordIdx,
4091 int ArgOffset,
unsigned ArgSize)
const {
4105 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4106 unsigned RBegin, REnd;
4111 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4116 ArgOffset = -4 * (ARM::R4 - RBegin);
4123 const TargetRegisterClass *RC =
4126 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4130 MachinePointerInfo(OrigArg, 4 * i));
4135 if (!MemOps.
empty())
4144 unsigned TotalArgRegsSaveSize,
4145 bool ForceMutable)
const {
4147 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4156 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4160bool ARMTargetLowering::splitValueIntoRegisterParts(
4162 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4164 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4176SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4178 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4179 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4192SDValue ARMTargetLowering::LowerFormalArguments(
4199 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4208 unsigned CurArgIdx = 0;
4220 unsigned ArgRegBegin = ARM::R4;
4221 for (
const CCValAssign &VA : ArgLocs) {
4227 if (!
Flags.isByVal())
4231 unsigned RBegin, REnd;
4233 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4239 int lastInsIndex = -1;
4243 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4246 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4250 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4251 CCValAssign &VA = ArgLocs[i];
4252 if (Ins[VA.
getValNo()].isOrigArg()) {
4253 std::advance(CurOrigArg,
4254 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4255 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4266 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4273 MVT::f64, dl, Chain, FIN,
4276 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4284 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4286 const TargetRegisterClass *RC;
4288 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4289 RC = &ARM::HPRRegClass;
4290 else if (RegVT == MVT::f32)
4291 RC = &ARM::SPRRegClass;
4292 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4293 RegVT == MVT::v4bf16)
4294 RC = &ARM::DPRRegClass;
4295 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4296 RegVT == MVT::v8bf16)
4297 RC = &ARM::QPRRegClass;
4298 else if (RegVT == MVT::i32)
4300 : &ARM::GPRRegClass;
4337 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4346 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4352 if (index != lastInsIndex)
4354 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4360 if (
Flags.isByVal()) {
4361 assert(Ins[index].isOrigArg() &&
4362 "Byval arguments cannot be implicit");
4366 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4400 lastInsIndex = index;
4407 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4408 TotalArgRegsSaveSize);
4412 "secure entry function must not be variadic", dl.
getDebugLoc()));
4422 assert(StackAlign &&
"data layout string is missing stack alignment");
4423 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4432 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4441 return CFP->getValueAPF().isPosZero();
4444 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4445 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4448 return CFP->getValueAPF().isPosZero();
4451 Op->getValueType(0) == MVT::f64) {
4455 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4466 const SDLoc &dl)
const {
4468 unsigned C = RHSC->getZExtValue();
4532 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4536 unsigned Mask =
LHS.getConstantOperandVal(1);
4538 uint64_t RHSV = RHSC->getZExtValue();
4539 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4541 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4555 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4558 LHS.getConstantOperandVal(1) < 31) {
4559 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4584 unsigned CompareType;
4587 CompareType = ARMISD::CMP;
4592 CompareType = ARMISD::CMPZ;
4602 bool Signaling)
const {
4603 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4609 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4618std::pair<SDValue, SDValue>
4621 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4633 switch (
Op.getOpcode()) {
4685 return std::make_pair(
Value, OverflowCmp);
4721 EVT VT =
Op.getValueType();
4722 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4725 switch (
Op.getOpcode()) {
4743 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4749 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4752 ARMcc, OverflowCmp);
4762 EVT VT =
Op.getValueType();
4763 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4773 switch (
Op->getOpcode()) {
4775 NewOpcode = ARMISD::UQADD8b;
4778 NewOpcode = ARMISD::QADD8b;
4781 NewOpcode = ARMISD::UQSUB8b;
4784 NewOpcode = ARMISD::QSUB8b;
4789 switch (
Op->getOpcode()) {
4791 NewOpcode = ARMISD::UQADD16b;
4794 NewOpcode = ARMISD::QADD16b;
4797 NewOpcode = ARMISD::UQSUB16b;
4800 NewOpcode = ARMISD::QSUB16b;
4808 DAG.
getNode(NewOpcode, dl, MVT::i32,
4819 unsigned Opc =
Cond.getOpcode();
4821 if (
Cond.getResNo() == 1 &&
4829 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4830 EVT VT =
Op.getValueType();
4832 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4840 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4841 const ConstantSDNode *CMOVTrue =
4843 const ConstantSDNode *CMOVFalse =
4846 if (CMOVTrue && CMOVFalse) {
4852 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
4854 False = SelectFalse;
4855 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
4861 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
4862 Cond.getOperand(3), DAG);
4877 bool &swpCmpOps,
bool &swpVselOps) {
4905 swpCmpOps = !swpCmpOps;
4906 swpVselOps = !swpVselOps;
4929 if (!Subtarget->hasFP64() && VT == MVT::f64) {
4931 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
4933 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
4947 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
4968 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
4970 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
4991 EVT VT =
Op.getValueType();
5013 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5026 int64_t PosVal = std::max(Val1, Val2);
5027 int64_t NegVal = std::min(Val1, Val2);
5039 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5042 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5074 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5079 if (*K != KTmp || V != VTmp)
5090bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5092 return !Subtarget->hasVFP2Base();
5094 return !Subtarget->hasFP64();
5096 return !Subtarget->hasFullFP16();
5101 EVT VT =
Op.getValueType();
5105 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5117 if (VT == MVT::i32 &&
5137 if (
Op.getValueType().isInteger()) {
5145 LHS.getValueType() ==
RHS.getValueType()) {
5146 EVT VT =
LHS.getValueType();
5152 Shift = DAG.
getNOT(dl, Shift, VT);
5158 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5159 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5162 unsigned Opcode = 0;
5164 if (TVal == ~FVal) {
5165 Opcode = ARMISD::CSINV;
5166 }
else if (TVal == ~FVal + 1) {
5167 Opcode = ARMISD::CSNEG;
5168 }
else if (TVal + 1 == FVal) {
5169 Opcode = ARMISD::CSINC;
5170 }
else if (TVal == FVal + 1) {
5171 Opcode = ARMISD::CSINC;
5180 if (Opcode != ARMISD::CSINC &&
5190 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5201 EVT VT =
TrueVal.getValueType();
5202 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5206 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5211 if (!
RHS.getNode()) {
5217 if (
LHS.getValueType() == MVT::i32) {
5228 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5229 TrueVal.getValueType() == MVT::f32 ||
5230 TrueVal.getValueType() == MVT::f64)) {
5244 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5254 if (Subtarget->hasFPARMv8Base() &&
5256 (
TrueVal.getValueType() == MVT::f16 ||
5257 TrueVal.getValueType() == MVT::f32 ||
5258 TrueVal.getValueType() == MVT::f64)) {
5259 bool swpCmpOps =
false;
5260 bool swpVselOps =
false;
5274 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5277 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5287 if (!
N->hasOneUse())
5290 if (!
N->getNumValues())
5292 EVT VT =
Op.getValueType();
5293 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5310 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5311 Ld->getPointerInfo(), Ld->getAlign(),
5312 Ld->getMemOperand()->getFlags());
5328 SDValue Ptr = Ld->getBasePtr();
5330 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5331 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5336 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5337 Ld->getPointerInfo().getWithOffset(4),
5339 Ld->getMemOperand()->getFlags());
5357 bool LHSSeenZero =
false;
5359 bool RHSSeenZero =
false;
5361 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5372 if (
LHS.getValueType() == MVT::f32) {
5378 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5390 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5391 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5406 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5418 unsigned Opc =
Cond.getOpcode();
5420 !Subtarget->isThumb1Only();
5421 if (
Cond.getResNo() == 1 &&
5431 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5437 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5439 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5454 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5459 if (!
RHS.getNode()) {
5467 unsigned Opc =
LHS.getOpcode();
5469 !Subtarget->isThumb1Only();
5481 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5488 ARMcc = DAG.
getConstant(CondCode, SDLoc(ARMcc), MVT::i32);
5491 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5495 if (
LHS.getValueType() == MVT::i32) {
5498 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5501 SDNodeFlags
Flags =
Op->getFlags();
5502 if (
Flags.hasNoNaNs() &&
5507 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5521 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5535 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5538 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5543 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5544 Addr,
Op.getOperand(2), JTI);
5548 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5552 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5555 DAG.
getLoad(PTy, dl, Chain, Addr,
5558 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5563 EVT VT =
Op.getValueType();
5566 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5567 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5575 const EVT OpTy =
Op.getOperand(0).getValueType();
5576 if (OpTy == MVT::v4f32)
5578 else if (OpTy == MVT::v4f16 && HasFullFP16)
5580 else if (OpTy == MVT::v8f16 && HasFullFP16)
5585 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5588 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5593 EVT VT =
Op.getValueType();
5597 bool IsStrict =
Op->isStrictFPOpcode();
5598 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5600 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5613 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5614 CallOptions, Loc, Chain);
5624 Loc,
Op.getValueType(), SrcVal);
5633 EVT VT =
Op.getValueType();
5635 EVT FromVT =
Op.getOperand(0).getValueType();
5637 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5639 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5640 Subtarget->hasFP64())
5642 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5643 Subtarget->hasFullFP16())
5645 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5646 Subtarget->hasMVEFloatOps())
5648 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5649 Subtarget->hasMVEFloatOps())
5652 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5669 EVT VT =
Op.getValueType();
5672 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5678 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5679 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5680 "Invalid type for custom lowering!");
5685 if (VT == MVT::v4f32)
5686 DestVecType = MVT::v4i32;
5687 else if (VT == MVT::v4f16 && HasFullFP16)
5688 DestVecType = MVT::v4i16;
5689 else if (VT == MVT::v8f16 && HasFullFP16)
5690 DestVecType = MVT::v8i16;
5696 switch (
Op.getOpcode()) {
5708 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5713 EVT VT =
Op.getValueType();
5716 if (isUnsupportedFloatingType(VT)) {
5726 CallOptions, SDLoc(
Op)).first;
5737 EVT VT =
Op.getValueType();
5741 bool UseNEON = !InGPR && Subtarget->hasNEON();
5748 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5755 if (SrcVT == MVT::f32) {
5758 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5761 }
else if (VT == MVT::f32)
5762 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5777 if (VT == MVT::f32) {
5789 if (SrcVT == MVT::f64)
5798 if (VT == MVT::f32) {
5811 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5819 EVT VT =
Op.getValueType();
5821 unsigned Depth =
Op.getConstantOperandVal(0);
5823 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5827 MachinePointerInfo());
5836 const ARMBaseRegisterInfo &ARI =
5837 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
5842 EVT VT =
Op.getValueType();
5844 unsigned Depth =
Op.getConstantOperandVal(0);
5849 MachinePointerInfo());
5857 return StringSwitch<Register>(
RegName)
5858 .Case(
"sp", ARM::SP)
5869 assert(
N->getValueType(0) == MVT::i64
5870 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
5873 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
5913 const APInt &APIntIndex = Index->getAPIntValue();
5915 NewIndex *= APIntIndex;
5944 EVT SrcVT =
Op.getValueType();
5945 EVT DstVT =
N->getValueType(0);
5947 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
5948 (DstVT == MVT::f16 || DstVT == MVT::bf16))
5949 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
5952 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
5953 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
5954 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
5961 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
5973 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
5981 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
5983 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
5985 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6005 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6014 EVT VT =
Op.getValueType();
6036 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6046 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6057 EVT VT =
Op.getValueType();
6078 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6099 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6151 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6179 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6209 EVT VT =
N->getValueType(0);
6210 if (VT.
isVector() && ST->hasNEON()) {
6219 if (ElemTy == MVT::i8) {
6227 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6230 unsigned NumBits = ElemTy.getSizeInBits();
6232 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6242 if (ElemTy == MVT::i64) {
6255 if (!ST->hasV6T2Ops())
6264 EVT VT =
N->getValueType(0);
6267 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6268 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6269 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6270 "Unexpected type for custom ctpop lowering");
6278 unsigned EltSize = 8;
6301 Op =
Op.getOperand(0);
6303 APInt SplatBits, SplatUndef;
6304 unsigned SplatBitSize;
6307 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6309 SplatBitSize > ElementBits)
6320 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6324 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6335 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6340 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6341 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6350 EVT VT =
N->getValueType(0);
6365 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6367 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6372 "unexpected vector shift opcode");
6374 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6375 unsigned VShiftOpc =
6376 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6377 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6383 EVT ShiftVT =
N->getOperand(1).getValueType();
6386 unsigned VShiftOpc =
6387 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6388 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6393 EVT VT =
N->getValueType(0);
6402 "Unknown shift to lower!");
6404 unsigned ShOpc =
N->getOpcode();
6405 if (ST->hasMVEIntegerOps()) {
6407 unsigned ShPartsOpc = ARMISD::LSLL;
6428 ShPartsOpc = ARMISD::LSRL;
6430 ShPartsOpc = ARMISD::ASRL;
6435 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6449 if (ST->isThumb1Only())
6454 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6458 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6462 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6470 bool Invert =
false;
6477 EVT VT =
Op.getValueType();
6485 assert(ST->hasMVEIntegerOps() &&
6486 "No hardware support for integer vector comparison!");
6488 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6509 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6513 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6523 switch (SetCCOpcode) {
6527 if (ST->hasMVEFloatOps()) {
6530 Invert =
true; [[fallthrough]];
6535 case ISD::SETLT: Swap =
true; [[fallthrough]];
6539 case ISD::SETLE: Swap =
true; [[fallthrough]];
6555 Result = DAG.
getNOT(dl, Result, VT);
6558 case ISD::SETUO: Invert =
true; [[fallthrough]];
6567 Result = DAG.
getNOT(dl, Result, VT);
6573 switch (SetCCOpcode) {
6576 if (ST->hasMVEIntegerOps()) {
6579 Invert =
true; [[fallthrough]];
6582 case ISD::SETLT: Swap =
true; [[fallthrough]];
6584 case ISD::SETLE: Swap =
true; [[fallthrough]];
6601 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6604 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6609 Result = DAG.
getNOT(dl, Result, VT);
6634 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6637 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6643 Result = DAG.
getNOT(dl, Result, VT);
6655 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6671 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6682 unsigned OpCmode, Imm;
6693 switch (SplatBitSize) {
6698 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6701 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6706 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6707 if ((SplatBits & ~0xff) == 0) {
6713 if ((SplatBits & ~0xff00) == 0) {
6716 Imm = SplatBits >> 8;
6726 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6727 if ((SplatBits & ~0xff) == 0) {
6733 if ((SplatBits & ~0xff00) == 0) {
6736 Imm = SplatBits >> 8;
6739 if ((SplatBits & ~0xff0000) == 0) {
6742 Imm = SplatBits >> 16;
6745 if ((SplatBits & ~0xff000000) == 0) {
6748 Imm = SplatBits >> 24;
6755 if ((SplatBits & ~0xffff) == 0 &&
6756 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6759 Imm = SplatBits >> 8;
6767 if ((SplatBits & ~0xffffff) == 0 &&
6768 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6771 Imm = SplatBits >> 16;
6787 unsigned ImmMask = 1;
6789 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6790 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6792 }
else if ((SplatBits & BitMask) != 0) {
6801 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6815 EVT VT =
Op.getValueType();
6816 bool IsDouble = (VT == MVT::f64);
6822 if (
ST->genExecuteOnly()) {
6824 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6825 "Unexpected architecture");
6843 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
6848 if (!
ST->hasVFP3Base())
6853 if (IsDouble && !Subtarget->hasFP64())
6860 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
6878 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
6887 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
6941 unsigned ExpectedElt = Imm;
6942 for (
unsigned i = 1; i < NumElts; ++i) {
6946 if (ExpectedElt == NumElts)
6949 if (M[i] < 0)
continue;
6950 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
6958 bool &ReverseVEXT,
unsigned &Imm) {
6960 ReverseVEXT =
false;
6971 unsigned ExpectedElt = Imm;
6972 for (
unsigned i = 1; i < NumElts; ++i) {
6976 if (ExpectedElt == NumElts * 2) {
6981 if (M[i] < 0)
continue;
6982 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
6997 return VT == MVT::v8i8 && M.size() == 8;
7002 if (Mask.size() == Elements * 2)
7003 return Index / Elements;
7004 return Mask[Index] == 0 ? 0 : 1;
7034 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7042 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7044 for (
unsigned j = 0; j < NumElts; j += 2) {
7045 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7046 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7051 if (M.size() == NumElts*2)
7066 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7069 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7071 for (
unsigned j = 0; j < NumElts; j += 2) {
7072 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7073 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7078 if (M.size() == NumElts*2)
7098 if (M.size() != NumElts && M.size() != NumElts*2)
7101 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7103 for (
unsigned j = 0; j < NumElts; ++j) {
7104 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7109 if (M.size() == NumElts*2)
7128 if (M.size() != NumElts && M.size() != NumElts*2)
7131 unsigned Half = NumElts / 2;
7132 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7134 for (
unsigned j = 0; j < NumElts; j += Half) {
7135 unsigned Idx = WhichResult;
7136 for (
unsigned k = 0; k < Half; ++k) {
7137 int MIdx = M[i + j + k];
7138 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7145 if (M.size() == NumElts*2)
7169 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7172 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7174 unsigned Idx = WhichResult * NumElts / 2;
7175 for (
unsigned j = 0; j < NumElts; j += 2) {
7176 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7177 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7183 if (M.size() == NumElts*2)
7202 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7205 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7207 unsigned Idx = WhichResult * NumElts / 2;
7208 for (
unsigned j = 0; j < NumElts; j += 2) {
7209 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7210 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7216 if (M.size() == NumElts*2)
7229 unsigned &WhichResult,
7232 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7233 return ARMISD::VTRN;
7234 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7235 return ARMISD::VUZP;
7236 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7237 return ARMISD::VZIP;
7241 return ARMISD::VTRN;
7243 return ARMISD::VUZP;
7245 return ARMISD::VZIP;
7254 if (NumElts != M.size())
7258 for (
unsigned i = 0; i != NumElts; ++i)
7259 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7268 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7276 int Ofs = Top ? 1 : 0;
7277 int Upper = SingleSource ? 0 : NumElts;
7278 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7279 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7281 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7290 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7299 unsigned Offset = Top ? 0 : 1;
7300 unsigned N = SingleSource ? 0 : NumElts;
7301 for (
unsigned i = 0; i < NumElts; i += 2) {
7302 if (M[i] >= 0 && M[i] != (
int)i)
7304 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7313 if (NumElts != M.size())
7321 unsigned Off0 = rev ? NumElts / 2 : 0;
7322 unsigned Off1 = rev ? 0 : NumElts / 2;
7323 for (
unsigned i = 0; i < NumElts; i += 2) {
7324 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7326 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7342 if (!ST->hasMVEFloatOps())
7347 if (VT != MVT::v8f16)
7368 for (
unsigned i = 1; i < 4; i++) {
7383 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7395 if (!ST->hasMVEFloatOps())
7400 if (VT != MVT::v4f32)
7416 for (
unsigned i = 1; i < 4; i++) {
7427 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7439 Val =
N->getAsZExtVal();
7441 if (ST->isThumb1Only()) {
7442 if (Val <= 255 || ~Val <= 255)
7454 EVT VT =
Op.getValueType();
7456 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7460 unsigned BitsPerBool;
7464 }
else if (NumElts == 4) {
7467 }
else if (NumElts == 8) {
7470 }
else if (NumElts == 16) {
7481 return U.get().isUndef() || U.get() == FirstOp;
7485 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7489 unsigned Bits32 = 0;
7490 for (
unsigned i = 0; i < NumElts; ++i) {
7494 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7496 Bits32 |= BoolMask << (i * BitsPerBool);
7502 for (
unsigned i = 0; i < NumElts; ++i) {
7515 if (!ST->hasMVEIntegerOps())
7519 EVT VT =
Op.getValueType();
7529 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7533 for (
unsigned I = 2;
I < NumElts;
I++) {
7549 switch (
N->getOpcode()) {
7560 return N->getOperand(1).getNode() ==
Op;
7562 switch (
N->getConstantOperandVal(0)) {
7563 case Intrinsic::arm_mve_add_predicated:
7564 case Intrinsic::arm_mve_mul_predicated:
7565 case Intrinsic::arm_mve_qadd_predicated:
7566 case Intrinsic::arm_mve_vhadd:
7567 case Intrinsic::arm_mve_hadd_predicated:
7568 case Intrinsic::arm_mve_vqdmulh:
7569 case Intrinsic::arm_mve_qdmulh_predicated:
7570 case Intrinsic::arm_mve_vqrdmulh:
7571 case Intrinsic::arm_mve_qrdmulh_predicated:
7572 case Intrinsic::arm_mve_vqdmull:
7573 case Intrinsic::arm_mve_vqdmull_predicated:
7575 case Intrinsic::arm_mve_sub_predicated:
7576 case Intrinsic::arm_mve_qsub_predicated:
7577 case Intrinsic::arm_mve_vhsub:
7578 case Intrinsic::arm_mve_hsub_predicated:
7579 return N->getOperand(2).getNode() ==
Op;
7594 EVT VT =
Op.getValueType();
7602 APInt SplatBits, SplatUndef;
7603 unsigned SplatBitSize;
7605 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7612 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7614 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7615 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7616 : SplatBitSize == 16 ? MVT::v8i16
7620 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7623 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7624 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7629 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7633 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7637 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7639 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7643 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7647 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7651 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7657 if (
ST->hasMVEIntegerOps() &&
7658 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7659 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7660 : SplatBitSize == 16 ? MVT::v8i16
7664 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7677 bool isOnlyLowElement =
true;
7678 bool usesOnlyOneValue =
true;
7679 bool hasDominantValue =
false;
7684 DenseMap<SDValue, unsigned> ValueCounts;
7686 for (
unsigned i = 0; i < NumElts; ++i) {
7691 isOnlyLowElement =
false;
7695 unsigned &
Count = ValueCounts[
V];
7698 if (++
Count > (NumElts / 2)) {
7699 hasDominantValue =
true;
7703 if (ValueCounts.
size() != 1)
7704 usesOnlyOneValue =
false;
7705 if (!
Value.getNode() && !ValueCounts.
empty())
7708 if (ValueCounts.
empty())
7720 if (hasDominantValue && EltSize <= 32) {
7729 ConstantSDNode *constIndex;
7736 if (VT !=
Value->getOperand(0).getValueType()) {
7739 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7744 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7749 if (!usesOnlyOneValue) {
7752 for (
unsigned I = 0;
I < NumElts; ++
I) {
7757 Ops.push_back(
Op.getOperand(
I));
7767 assert(FVT == MVT::f32 || FVT == MVT::f16);
7768 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7769 for (
unsigned i = 0; i < NumElts; ++i)
7774 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7778 if (usesOnlyOneValue) {
7781 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7805 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7825 if (EltSize >= 32) {
7831 for (
unsigned i = 0; i < NumElts; ++i)
7845 for (
unsigned i = 0 ; i < NumElts; ++i) {
7864 EVT VT =
Op.getValueType();
7867 struct ShuffleSourceInfo {
7869 unsigned MinElt = std::numeric_limits<unsigned>::max();
7870 unsigned MaxElt = 0;
7880 int WindowScale = 1;
7882 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7890 for (
unsigned i = 0; i < NumElts; ++i) {
7905 SDValue SourceVec =
V.getOperand(0);
7907 if (Source == Sources.
end())
7911 unsigned EltNo =
V.getConstantOperandVal(1);
7918 if (Sources.
size() > 2)
7924 for (
auto &Source : Sources) {
7925 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
7926 if (SrcEltTy.
bitsLT(SmallestEltTy))
7927 SmallestEltTy = SrcEltTy;
7929 unsigned ResMultiplier =
7937 for (
auto &Src : Sources) {
7938 EVT SrcVT = Src.ShuffleVec.getValueType();
7942 if (SrcVTSize == VTSize)
7951 if (SrcVTSize < VTSize) {
7952 if (2 * SrcVTSize != VTSize)
7958 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
7962 if (SrcVTSize != 2 * VTSize)
7965 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
7970 if (Src.MinElt >= NumSrcElts) {
7975 Src.WindowBase = -NumSrcElts;
7976 }
else if (Src.MaxElt < NumSrcElts) {
7990 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
7993 Src.WindowBase = -Src.MinElt;
8000 for (
auto &Src : Sources) {
8001 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8002 if (SrcEltTy == SmallestEltTy)
8005 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8007 Src.WindowBase *= Src.WindowScale;
8012 for (
auto Src : Sources)
8013 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8021 if (
Entry.isUndef())
8030 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8033 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8037 int *LaneMask = &
Mask[i * ResMultiplier];
8039 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8040 ExtractBase += NumElts * (Src - Sources.begin());
8041 for (
int j = 0;
j < LanesDefined; ++
j)
8042 LaneMask[j] = ExtractBase + j;
8048 assert(Sources.size() <= 2 &&
"Too many sources!");
8051 for (
unsigned i = 0; i < Sources.size(); ++i)
8058 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8080 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8100 unsigned PFIndexes[4];
8101 for (
unsigned i = 0; i != 4; ++i) {
8105 PFIndexes[i] = M[i];
8109 unsigned PFTableIndex =
8110 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8112 unsigned Cost = (PFEntry >> 30);
8118 bool ReverseVEXT, isV_UNDEF;
8119 unsigned Imm, WhichResult;
8122 if (EltSize >= 32 ||
8129 else if (Subtarget->hasNEON() &&
8134 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8137 else if (Subtarget->hasMVEIntegerOps() &&
8141 else if (Subtarget->hasMVEIntegerOps() &&
8155 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8156 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8157 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8160 if (LHSID == (1*9+2)*9+3)
return LHS;
8161 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8175 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8178 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8181 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8186 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8191 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8218 for (
int I : ShuffleMask)
8222 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8, V1,
8225 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8, V1, V2,
8231 EVT VT =
Op.getValueType();
8233 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8234 "Expect an v8i16/v16i8 type");
8240 std::vector<int> NewMask;
8244 NewMask.push_back(i);
8274 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8284 if (VT != MVT::v16i1)
8285 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8300 EVT VT =
Op.getValueType();
8304 assert(ST->hasMVEIntegerOps() &&
8305 "No support for vector shuffle of boolean predicates");
8315 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8331 "Expected identical vector type in expanded i1 shuffle!");
8335 PredAsVector2, ShuffleMask);
8340 if (VT == MVT::v2i1) {
8341 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8344 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8346 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8357 EVT VT =
Op.getValueType();
8361 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8362 "Unexpected vector type");
8364 int QuarterSize = NumElts / 4;
8373 for (
int i = 0; i <
Length; i++) {
8374 if (ShuffleMask[Start + i] >= 0) {
8375 if (ShuffleMask[Start + i] %
Length != i)
8377 MovIdx = ShuffleMask[Start + i] /
Length;
8385 for (
int i = 1; i <
Length; i++) {
8386 if (ShuffleMask[Start + i] >= 0 &&
8387 (ShuffleMask[Start + i] /
Length != MovIdx ||
8388 ShuffleMask[Start + i] %
Length != i))
8394 for (
int Part = 0; Part < 4; ++Part) {
8396 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8410 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8415 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8417 for (
int Part = 0; Part < 4; ++Part)
8418 for (
int i = 0; i < QuarterSize; i++)
8420 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8422 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8425 for (
int Part = 0; Part < 4; ++Part)
8441 EVT VT =
Op.getValueType();
8453 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8457 if (Mask[i] != i + BaseOffset) {
8458 if (OffElement == -1)
8464 return NonUndef > 2 && OffElement != -1;
8468 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8470 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8481 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8492 EVT VT =
Op.getValueType();
8496 if (ST->hasMVEIntegerOps() && EltSize == 1)
8507 if (EltSize <= 32) {
8511 if (Lane == -1) Lane = 0;
8522 bool IsScalarToVector =
true;
8525 IsScalarToVector =
false;
8528 if (IsScalarToVector)
8531 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT, V1,
8535 bool ReverseVEXT =
false;
8537 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8540 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V2,
8545 return DAG.
getNode(ARMISD::VREV64, dl, VT, V1);
8547 return DAG.
getNode(ARMISD::VREV32, dl, VT, V1);
8549 return DAG.
getNode(ARMISD::VREV16, dl, VT, V1);
8552 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V1,
8561 unsigned WhichResult = 0;
8562 bool isV_UNDEF =
false;
8563 if (ST->hasNEON()) {
8565 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8572 if (ST->hasMVEIntegerOps()) {
8574 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2, V1,
8577 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V2,
8580 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V1,
8607 }) &&
"Unexpected shuffle index into UNDEF operand!");
8610 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8613 assert((WhichResult == 0) &&
8614 "In-place shuffle of concat can only have one result!");
8623 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8627 for (
bool Top : {
false,
true}) {
8628 for (
bool SingleSource : {
false,
true}) {
8629 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8634 SingleSource ? V1 : V2);
8650 unsigned PFIndexes[4];
8651 for (
unsigned i = 0; i != 4; ++i) {
8652 if (ShuffleMask[i] < 0)
8655 PFIndexes[i] = ShuffleMask[i];
8659 unsigned PFTableIndex =
8660 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8662 unsigned Cost = (PFEntry >> 30);
8668 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8669 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8679 if (EltSize >= 32) {
8687 for (
unsigned i = 0; i < NumElts; ++i) {
8688 if (ShuffleMask[i] < 0)
8692 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8700 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8704 if (ST->hasNEON() && VT == MVT::v8i8)
8708 if (ST->hasMVEIntegerOps())
8717 EVT VecVT =
Op.getOperand(0).getValueType();
8720 assert(ST->hasMVEIntegerOps() &&
8721 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8724 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8725 unsigned Lane =
Op.getConstantOperandVal(2);
8726 unsigned LaneWidth =
8728 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8733 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8746 if (Subtarget->hasMVEIntegerOps() &&
8747 Op.getValueType().getScalarSizeInBits() == 1)
8771 IVecIn, IElt, Lane);
8780 EVT VecVT =
Op.getOperand(0).getValueType();
8783 assert(ST->hasMVEIntegerOps() &&
8784 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8787 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8788 unsigned Lane =
Op.getConstantOperandVal(1);
8789 unsigned LaneWidth =
8811 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8820 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8821 "Unexpected custom CONCAT_VECTORS lowering");
8823 "Unexpected custom CONCAT_VECTORS lowering");
8824 assert(ST->hasMVEIntegerOps() &&
8825 "CONCAT_VECTORS lowering only supported for MVE");
8829 EVT Op2VT = V2.getValueType();
8830 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8831 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8832 "Unexpected i1 concat operations!");
8845 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8850 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8859 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8860 EVT NewVT = NewV.getValueType();
8861 EVT ConcatVT = ConVec.getValueType();
8862 unsigned ExtScale = 1;
8863 if (NewVT == MVT::v2f64) {
8864 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8877 ConVec = ExtractInto(NewV1, ConVec, j);
8878 ConVec = ExtractInto(NewV2, ConVec, j);
8882 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8888 while (ConcatOps.
size() > 1) {
8889 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8892 ConcatOps[
I / 2] = ConcatPair(V1, V2);
8896 return ConcatOps[0];
8901 EVT VT =
Op->getValueType(0);
8907 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
8908 "unexpected CONCAT_VECTORS");
8929 EVT VT =
Op.getValueType();
8935 "Unexpected custom EXTRACT_SUBVECTOR lowering");
8936 assert(ST->hasMVEIntegerOps() &&
8937 "EXTRACT_SUBVECTOR lowering only supported for MVE");
8947 EVT SubVT = MVT::v4i32;
8949 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
8959 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8964 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
8973 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
8980 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
8981 EVT VT =
N->getValueType(0);
8982 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
8983 "Expected a vector i1 type!");
8985 EVT FromVT =
Op.getValueType();
8996 if (!Subtarget->hasMVEIntegerOps())
8999 EVT ToVT =
N->getValueType(0);
9042 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9044 EVT FromVT =
N->getOperand(0).getValueType();
9045 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9056 if (!Subtarget->hasMVEIntegerOps())
9061 EVT ToVT =
N->getValueType(0);
9062 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9065 EVT FromVT =
Op.getValueType();
9066 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9080 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9081 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9093 EVT VT =
N->getValueType(0);
9095 SDNode *BVN =
N->getOperand(0).getNode();
9100 unsigned HiElt = 1 - LoElt;
9105 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9121 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9122 SDNode *Elt =
N->getOperand(i).getNode();
9125 unsigned HalfSize = EltSize / 2;
9127 if (!
isIntN(HalfSize,
C->getSExtValue()))
9130 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9169 switch (OrigSimpleTy) {
9185 unsigned ExtOpcode) {
9208 if (ExtendedTy == LD->getMemoryVT())
9209 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9210 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9211 LD->getMemOperand()->getFlags());
9217 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9218 LD->getMemoryVT(), LD->getAlign(),
9219 LD->getMemOperand()->getFlags());
9232 N->getOperand(0)->getValueType(0),
9238 "Expected extending load");
9244 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9253 SDNode *BVN =
N->getOperand(0).getNode();
9255 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9263 EVT VT =
N->getValueType(0);
9269 for (
unsigned i = 0; i != NumElts; ++i) {
9270 const APInt &CInt =
N->getConstantOperandAPInt(i);
9279 unsigned Opcode =
N->getOpcode();
9281 SDNode *N0 =
N->getOperand(0).getNode();
9282 SDNode *N1 =
N->getOperand(1).getNode();
9290 unsigned Opcode =
N->getOpcode();
9292 SDNode *N0 =
N->getOperand(0).getNode();
9293 SDNode *N1 =
N->getOperand(1).getNode();
9303 EVT VT =
Op.getValueType();
9305 "unexpected type for custom-lowering ISD::MUL");
9306 SDNode *N0 =
Op.getOperand(0).getNode();
9307 SDNode *N1 =
Op.getOperand(1).getNode();
9308 unsigned NewOpc = 0;
9312 if (isN0SExt && isN1SExt)
9313 NewOpc = ARMISD::VMULLs;
9317 if (isN0ZExt && isN1ZExt)
9318 NewOpc = ARMISD::VMULLu;
9319 else if (isN1SExt || isN1ZExt) {
9323 NewOpc = ARMISD::VMULLs;
9326 NewOpc = ARMISD::VMULLu;
9330 NewOpc = ARMISD::VMULLu;
9336 if (VT == MVT::v2i64)
9353 "unexpected types for extended operands to VMULL");
9354 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9389 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9423 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9426 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9447 EVT VT =
Op.getValueType();
9448 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9449 "unexpected type for custom-lowering ISD::SDIV");
9456 if (VT == MVT::v8i8) {
9484 EVT VT =
Op.getValueType();
9485 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9486 "unexpected type for custom-lowering ISD::UDIV");
9493 if (VT == MVT::v8i8) {
9532 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9535 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9539 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9560 EVT VT =
N->getValueType(0);
9573 Result = DAG.
getNode(ARMISD::ADDE,
DL, VTs,
Op.getOperand(0),
9574 Op.getOperand(1), Carry);
9587 Result = DAG.
getNode(ARMISD::SUBE,
DL, VTs,
Op.getOperand(0),
9588 Op.getOperand(1), Carry);
9605 EVT VT =
Op.getValueType();
9606 assert((VT == MVT::i32 || VT == MVT::i64) &&
9607 "unexpected type for custom lowering DIV");
9613 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9615 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9622 for (
auto AI : {1, 0}) {
9624 Args.emplace_back(Operand,
9641ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9649 const bool MinSize =
ST.hasMinSize();
9650 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9651 :
ST.hasDivideInARMMode();
9655 if (
N->getOperand(0).getValueType().isVector())
9660 if (!(MinSize && HasDivide))
9673 if (Divisor.
sgt(128))
9681 assert(
Op.getValueType() == MVT::i32 &&
9682 "unexpected type for custom lowering DIV");
9685 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9688 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9694 if (
N->getValueType(0) == MVT::i32)
9695 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9698 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9702void ARMTargetLowering::ExpandDIV_Windows(
9707 assert(
Op.getValueType() == MVT::i64 &&
9708 "unexpected type for custom lowering DIV");
9723std::pair<SDValue, SDValue>
9724ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9730 EVT MemVT =
LD->getMemoryVT();
9731 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9735 unsigned AS =
LD->getAddressSpace();
9736 Align Alignment =
LD->getAlign();
9738 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9741 Alignment <= llvm::Align(2)) {
9744 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9750 Opts, dl,
LD->getChain());
9775 EVT MemVT =
ST->getMemoryVT();
9776 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9780 unsigned AS =
ST->getAddressSpace();
9781 Align Alignment =
ST->getAlign();
9783 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9786 Alignment <= llvm::Align(2)) {
9792 if (
ST->isTruncatingStore())
9796 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9800 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9801 dl,
ST->getChain());
9803 return CallResult.second;
9814 EVT MemVT = LD->getMemoryVT();
9815 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9816 MemVT == MVT::v16i1) &&
9817 "Expected a predicate type!");
9818 assert(MemVT ==
Op.getValueType());
9820 "Expected a non-extending load");
9821 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9835 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9837 LD->getMemOperand());
9843 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9844 if (MemVT != MVT::v16i1)
9853 EVT MemVT =
LD->getMemoryVT();
9855 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9856 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9857 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9858 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9861 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9862 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9867 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9868 auto Pair = LowerAEABIUnalignedLoad(
SDValue(
N, 0), DAG);
9870 Results.push_back(Pair.first);
9871 Results.push_back(Pair.second);
9878 EVT MemVT = ST->getMemoryVT();
9879 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9880 MemVT == MVT::v16i1) &&
9881 "Expected a predicate type!");
9882 assert(MemVT == ST->getValue().getValueType());
9883 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9884 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9889 SDValue Build = ST->getValue();
9890 if (MemVT != MVT::v16i1) {
9903 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9909 ST->getChain(), dl, GRP, ST->getBasePtr(),
9911 ST->getMemOperand());
9917 EVT MemVT =
ST->getMemoryVT();
9919 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9920 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
9921 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9922 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
9923 SDNode *
N =
Op.getNode();
9936 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
9937 MemVT,
ST->getMemOperand());
9938 }
else if (Subtarget->hasMVEIntegerOps() &&
9939 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9940 MemVT == MVT::v16i1))) {
9942 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9943 return LowerAEABIUnalignedStore(
Op, DAG);
9950 (
N->getOpcode() == ARMISD::VMOVIMM &&
9956 MVT VT =
Op.getSimpleValueType();
9958 SDValue PassThru =
N->getPassThru();
9969 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
9970 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
9971 N->getExtensionType(),
N->isExpandingLoad());
9974 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
9976 if (!PassThru.
isUndef() && !PassThruIsCastZero)
9983 if (!ST->hasMVEIntegerOps())
9987 unsigned BaseOpcode = 0;
9988 switch (
Op->getOpcode()) {
10004 unsigned NumActiveLanes = NumElts;
10006 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10007 NumActiveLanes == 2) &&
10008 "Only expected a power 2 vector size");
10012 while (NumActiveLanes > 4) {
10013 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10015 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10016 NumActiveLanes /= 2;
10020 if (NumActiveLanes == 4) {
10030 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10031 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10032 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10038 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10042 if (EltVT !=
Op->getValueType(0))
10049 if (!ST->hasMVEFloatOps())
10056 if (!ST->hasNEON())
10064 unsigned PairwiseIntrinsic = 0;
10065 switch (
Op->getOpcode()) {
10069 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10072 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10075 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10078 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10084 unsigned NumActiveLanes = NumElts;
10086 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10087 NumActiveLanes == 2) &&
10088 "Only expected a power 2 vector size");
10094 VT =
Lo.getValueType();
10096 NumActiveLanes /= 2;
10100 while (NumActiveLanes > 1) {
10102 NumActiveLanes /= 2;
10109 if (EltVT !=
Op.getValueType()) {
10110 unsigned Extend = 0;
10111 switch (
Op->getOpcode()) {
10123 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10168 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10174 SDLoc dl(V.getNode());
10175 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10185 assert(
N->getValueType(0) == MVT::i64 &&
10186 "AtomicCmpSwap on types less than 64 should be legal");
10195 ARM::CMP_SWAP_64,
SDLoc(
N),
10196 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10215 EVT VT =
Op.getValueType();
10224 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10226 Chain, IsSignaling);
10227 if (!
RHS.getNode()) {
10243 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10245 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10246 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10263 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10266 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10279 if (!IsSigned && Subtarget->isThumb1Only()) {
10297 Sub1Result, Sub1Result, Flags1);
10312 if (
Op.getValueType() != MVT::i32)
10326 unsigned Opcode = ARMISD::SUBC;
10335 bool CanUseAdd =
false;
10351 Opcode = ARMISD::ADDC;
10375 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10376 GTCondValue, Flags);
10380 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10381 LTCondValue, Flags);
10383 if (
Op.getValueType() != MVT::i32)
10391 switch (
Op.getOpcode()) {
10423 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10427 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10428 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10450 return LowerSET_FPMODE(
Op, DAG);
10452 return LowerRESET_FPMODE(
Op, DAG);
10456 !
Op.getValueType().isVector())
10457 return LowerDIV_Windows(
Op, DAG,
true);
10461 !
Op.getValueType().isVector())
10462 return LowerDIV_Windows(
Op, DAG,
false);
10473 return LowerALUO(
Op, DAG);
10481 EVT MemVT = LD->getMemoryVT();
10482 if (Subtarget->hasMVEIntegerOps() &&
10483 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10484 MemVT == MVT::v16i1))
10487 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10493 return LowerSTORE(
Op, DAG, Subtarget);
10518 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10527 return LowerSPONENTRY(
Op, DAG);
10529 return LowerFP_TO_BF16(
Op, DAG);
10530 case ARMISD::WIN__DBZCHK:
return SDValue();
10533 return LowerCMP(
Op, DAG);
10535 return LowerABS(
Op, DAG);
10540 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10541 Op.getOperand(1).getValueType() == MVT::bf16) &&
10542 "Expected custom lowering of rounding operations only for f16");
10545 {
Op.getOperand(0),
Op.getOperand(1)});
10546 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10547 {Ext.getValue(1), Ext.getValue(0)});
10554 unsigned IntNo =
N->getConstantOperandVal(0);
10556 if (IntNo == Intrinsic::arm_smlald)
10557 Opc = ARMISD::SMLALD;
10558 else if (IntNo == Intrinsic::arm_smlaldx)
10559 Opc = ARMISD::SMLALDX;
10560 else if (IntNo == Intrinsic::arm_smlsld)
10561 Opc = ARMISD::SMLSLD;
10562 else if (IntNo == Intrinsic::arm_smlsldx)
10563 Opc = ARMISD::SMLSLDX;
10569 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10573 N->getOperand(1),
N->getOperand(2),
10585 switch (
N->getOpcode()) {
10592 Res = ExpandBITCAST(
N, DAG, Subtarget);
10601 Res = LowerREM(
N, DAG);
10605 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10622 "can only expand DIV on Windows");
10634 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10663 "ROPI/RWPI not currently supported with SjLj");
10672 bool isThumb = Subtarget->isThumb();
10673 bool isThumb2 = Subtarget->
isThumb2();
10676 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10682 : &ARM::GPRRegClass;
10700 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10706 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10712 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10730 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10735 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10740 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10745 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10751 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10766 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10772 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10788 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10795 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10796 : &ARM::GPRnopcRegClass;
10800 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10801 unsigned MaxCSNum = 0;
10802 for (MachineBasicBlock &BB : *MF) {
10808 for (MachineInstr &
II : BB) {
10809 if (!
II.isEHLabel())
10812 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10813 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10815 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10816 for (
unsigned Idx : CallSiteIdxs) {
10817 CallSiteNumToLPad[Idx].push_back(&BB);
10818 MaxCSNum = std::max(MaxCSNum, Idx);
10825 std::vector<MachineBasicBlock*> LPadList;
10826 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10827 LPadList.reserve(CallSiteNumToLPad.
size());
10828 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10829 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10830 for (MachineBasicBlock *
MBB : MBBList) {
10831 LPadList.push_back(
MBB);
10836 assert(!LPadList.empty() &&
10837 "No landing pad destinations for the dispatch jump table!");
10840 MachineJumpTableInfo *JTI =
10847 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10850 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10852 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10855 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10859 MF->insert(MF->end(), DispatchBB);
10860 MF->insert(MF->end(), DispContBB);
10861 MF->insert(MF->end(), TrapBB);
10865 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10867 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10871 MachineInstrBuilder MIB;
10872 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10874 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10884 unsigned NumLPads = LPadList.size();
10885 if (Subtarget->isThumb2()) {
10886 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10887 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10893 if (NumLPads < 256) {
10894 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10896 .
addImm(LPadList.size())
10899 Register VReg1 =
MRI->createVirtualRegister(TRC);
10900 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10901 .
addImm(NumLPads & 0xFFFF)
10904 unsigned VReg2 = VReg1;
10905 if ((NumLPads & 0xFFFF0000) != 0) {
10906 VReg2 =
MRI->createVirtualRegister(TRC);
10907 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10913 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
10919 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
10924 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10925 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
10929 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10930 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
10937 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
10941 }
else if (Subtarget->isThumb()) {
10942 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10943 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
10949 if (NumLPads < 256) {
10950 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
10955 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10960 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
10961 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
10963 Register VReg1 =
MRI->createVirtualRegister(TRC);
10964 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
10968 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
10974 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
10979 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10980 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
10986 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10987 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
10991 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10992 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
10998 MachineMemOperand *JTMMOLd =
11002 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11003 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11009 unsigned NewVReg6 = NewVReg5;
11010 if (IsPositionIndependent) {
11011 NewVReg6 =
MRI->createVirtualRegister(TRC);
11012 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11019 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11023 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11024 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11030 if (NumLPads < 256) {
11031 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11035 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11036 Register VReg1 =
MRI->createVirtualRegister(TRC);
11037 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11038 .
addImm(NumLPads & 0xFFFF)
11041 unsigned VReg2 = VReg1;
11042 if ((NumLPads & 0xFFFF0000) != 0) {
11043 VReg2 =
MRI->createVirtualRegister(TRC);
11044 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11050 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11055 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11060 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11061 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11063 Register VReg1 =
MRI->createVirtualRegister(TRC);
11064 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11069 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11080 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11081 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11086 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11087 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11091 MachineMemOperand *JTMMOLd =
11094 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11095 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11102 if (IsPositionIndependent) {
11103 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11108 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11115 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11116 for (MachineBasicBlock *CurMBB : LPadList) {
11117 if (SeenMBBs.
insert(CurMBB).second)
11124 for (MachineBasicBlock *BB : InvokeBBs) {
11128 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11129 while (!Successors.empty()) {
11130 MachineBasicBlock *SMBB = Successors.pop_back_val();
11132 BB->removeSuccessor(SMBB);
11138 BB->normalizeSuccProbs();
11145 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11146 if (!
II->isCall())
continue;
11148 DenseSet<unsigned> DefRegs;
11150 OI =
II->operands_begin(), OE =
II->operands_end();
11152 if (!OI->isReg())
continue;
11153 DefRegs.
insert(OI->getReg());
11156 MachineInstrBuilder MIB(*MF, &*
II);
11158 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11159 unsigned Reg = SavedRegs[i];
11160 if (Subtarget->isThumb2() &&
11161 !ARM::tGPRRegClass.contains(
Reg) &&
11162 !ARM::hGPRRegClass.contains(
Reg))
11164 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11166 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11178 for (MachineBasicBlock *MBBLPad : MBBLPads)
11179 MBBLPad->setIsEHPad(
false);
11182 MI.eraseFromParent();
11195static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11197 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11198 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11200 return LdSize == 4 ? ARM::tLDRi
11201 : LdSize == 2 ? ARM::tLDRHi
11202 : LdSize == 1 ? ARM::tLDRBi : 0;
11204 return LdSize == 4 ? ARM::t2LDR_POST
11205 : LdSize == 2 ? ARM::t2LDRH_POST
11206 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11207 return LdSize == 4 ? ARM::LDR_POST_IMM
11208 : LdSize == 2 ? ARM::LDRH_POST
11209 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11214static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11216 return StSize == 16 ? ARM::VST1q32wb_fixed
11217 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11219 return StSize == 4 ? ARM::tSTRi
11220 : StSize == 2 ? ARM::tSTRHi
11221 : StSize == 1 ? ARM::tSTRBi : 0;
11223 return StSize == 4 ? ARM::t2STR_POST
11224 : StSize == 2 ? ARM::t2STRH_POST
11225 : StSize == 1 ? ARM::t2STRB_POST : 0;
11226 return StSize == 4 ? ARM::STR_POST_IMM
11227 : StSize == 2 ? ARM::STRH_POST
11228 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11235 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11236 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11237 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11238 assert(LdOpc != 0 &&
"Should have a load opcode");
11245 }
else if (IsThumb1) {
11251 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11256 }
else if (IsThumb2) {
11276 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11277 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11278 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11279 assert(StOpc != 0 &&
"Should have a store opcode");
11281 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11286 }
else if (IsThumb1) {
11293 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11298 }
else if (IsThumb2) {
11299 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11305 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11320 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11326 unsigned SizeVal =
MI.getOperand(2).getImm();
11327 unsigned Alignment =
MI.getOperand(3).getImm();
11332 unsigned UnitSize = 0;
11333 const TargetRegisterClass *TRC =
nullptr;
11334 const TargetRegisterClass *VecTRC =
nullptr;
11336 bool IsThumb1 = Subtarget->isThumb1Only();
11337 bool IsThumb2 = Subtarget->isThumb2();
11338 bool IsThumb = Subtarget->isThumb();
11340 if (Alignment & 1) {
11342 }
else if (Alignment & 2) {
11347 Subtarget->hasNEON()) {
11348 if ((Alignment % 16 == 0) && SizeVal >= 16)
11350 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11359 bool IsNeon = UnitSize >= 8;
11360 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11362 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11363 : UnitSize == 8 ? &ARM::DPRRegClass
11366 unsigned BytesLeft = SizeVal % UnitSize;
11367 unsigned LoopSize = SizeVal - BytesLeft;
11369 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11373 unsigned srcIn = src;
11374 unsigned destIn = dest;
11375 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11376 Register srcOut =
MRI.createVirtualRegister(TRC);
11377 Register destOut =
MRI.createVirtualRegister(TRC);
11378 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11380 IsThumb1, IsThumb2);
11382 IsThumb1, IsThumb2);
11390 for (
unsigned i = 0; i < BytesLeft; i++) {
11391 Register srcOut =
MRI.createVirtualRegister(TRC);
11392 Register destOut =
MRI.createVirtualRegister(TRC);
11393 Register scratch =
MRI.createVirtualRegister(TRC);
11395 IsThumb1, IsThumb2);
11397 IsThumb1, IsThumb2);
11401 MI.eraseFromParent();
11427 MF->
insert(It, loopMBB);
11428 MF->
insert(It, exitMBB);
11431 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11441 Register varEnd =
MRI.createVirtualRegister(TRC);
11442 if (Subtarget->useMovt()) {
11443 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11446 }
else if (Subtarget->genExecuteOnly()) {
11447 assert(IsThumb &&
"Non-thumb expected to have used movt");
11456 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11457 MachineMemOperand *CPMMO =
11481 MachineBasicBlock *entryBB = BB;
11483 Register varLoop =
MRI.createVirtualRegister(TRC);
11484 Register varPhi =
MRI.createVirtualRegister(TRC);
11485 Register srcLoop =
MRI.createVirtualRegister(TRC);
11486 Register srcPhi =
MRI.createVirtualRegister(TRC);
11487 Register destLoop =
MRI.createVirtualRegister(TRC);
11488 Register destPhi =
MRI.createVirtualRegister(TRC);
11496 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11502 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11504 IsThumb1, IsThumb2);
11506 IsThumb1, IsThumb2);
11510 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11516 MachineInstrBuilder MIB =
11518 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11527 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11536 auto StartOfExit = exitMBB->
begin();
11540 unsigned srcIn = srcLoop;
11541 unsigned destIn = destLoop;
11542 for (
unsigned i = 0; i < BytesLeft; i++) {
11543 Register srcOut =
MRI.createVirtualRegister(TRC);
11544 Register destOut =
MRI.createVirtualRegister(TRC);
11545 Register scratch =
MRI.createVirtualRegister(TRC);
11546 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11547 IsThumb1, IsThumb2);
11548 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11549 IsThumb1, IsThumb2);
11554 MI.eraseFromParent();
11562 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11565 assert(TM.getTargetTriple().isOSWindows() &&
11566 "__chkstk is only supported on Windows");
11567 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11587 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11588 if (ChkStkLibcall == RTLIB::Unsupported)
11592 switch (TM.getCodeModel()) {
11634 MI.eraseFromParent();
11643 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11658 .
addReg(
MI.getOperand(0).getReg())
11666 MI.eraseFromParent();
11690 if (miI == BB->
end()) {
11692 if (Succ->isLiveIn(ARM::CPSR))
11698 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11710 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11711 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11717 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11718 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11724 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11725 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11728 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11729 .
addUse(TotalIterationsReg)
11736 return TotalIterationsReg;
11747 Register TotalIterationsReg,
bool IsMemcpy) {
11754 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11755 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11756 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11764 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11765 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11766 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11773 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11774 Register RemainingLoopIterationsReg =
11775 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11776 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11777 .
addUse(TotalIterationsReg)
11779 .
addUse(RemainingLoopIterationsReg)
11783 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11784 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11785 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11786 .
addUse(ElementCountReg)
11788 .
addUse(RemainingElementsReg)
11792 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11793 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11794 .
addUse(PredCounterPhiReg)
11799 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11800 .
addUse(PredCounterPhiReg)
11808 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11809 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11818 SrcValueReg = OpSrcReg;
11820 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11831 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11832 .
addUse(LoopCounterPhiReg)
11835 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11836 .
addUse(RemainingLoopIterationsReg)
11854 "Invalid call instruction for a KCFI check");
11857 switch (
MBBI->getOpcode()) {
11860 case ARM::BLX_pred:
11861 case ARM::BLX_noip:
11862 case ARM::BLX_pred_noip:
11864 TargetOp = &
MBBI->getOperand(0);
11866 case ARM::TCRETURNri:
11867 case ARM::TCRETURNrinotr12:
11868 case ARM::TAILJMPr:
11869 case ARM::TAILJMPr4:
11870 TargetOp = &
MBBI->getOperand(0);
11876 case ARM::tBLXr_noip:
11877 case ARM::tBX_CALL:
11878 TargetOp = &
MBBI->getOperand(2);
11881 case ARM::tTAILJMPr:
11882 TargetOp = &
MBBI->getOperand(0);
11888 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11892 unsigned KCFICheckOpcode;
11893 if (Subtarget->isThumb()) {
11894 if (Subtarget->isThumb2()) {
11895 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11897 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11900 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11914 bool isThumb2 = Subtarget->isThumb2();
11915 switch (
MI.getOpcode()) {
11922 case ARM::tLDR_postidx: {
11926 .
add(
MI.getOperand(2))
11927 .
add(
MI.getOperand(3))
11928 .
add(
MI.getOperand(4))
11929 .
add(
MI.getOperand(0))
11931 MI.eraseFromParent();
11935 case ARM::MVE_MEMCPYLOOPINST:
11936 case ARM::MVE_MEMSETLOOPINST: {
11966 Register OpDestReg =
MI.getOperand(0).getReg();
11967 Register OpSrcReg =
MI.getOperand(1).getReg();
11968 Register OpSizeReg =
MI.getOperand(2).getReg();
11988 if (TpExit == BB) {
11990 "block containing memcpy/memset Pseudo");
12003 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12005 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12008 Properties.resetNoPHIs();
12020 MI.eraseFromParent();
12030 case ARM::t2STR_preidx:
12031 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12033 case ARM::t2STRB_preidx:
12034 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12036 case ARM::t2STRH_preidx:
12037 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12040 case ARM::STRi_preidx:
12041 case ARM::STRBi_preidx: {
12042 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12043 : ARM::STRB_PRE_IMM;
12045 unsigned Offset =
MI.getOperand(4).getImm();
12053 .
add(
MI.getOperand(0))
12054 .
add(
MI.getOperand(1))
12055 .
add(
MI.getOperand(2))
12057 .
add(
MI.getOperand(5))
12058 .
add(
MI.getOperand(6))
12060 MI.eraseFromParent();
12063 case ARM::STRr_preidx:
12064 case ARM::STRBr_preidx:
12065 case ARM::STRH_preidx: {
12067 switch (
MI.getOpcode()) {
12069 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12070 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12071 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12076 MI.eraseFromParent();
12080 case ARM::tMOVCCr_pseudo: {
12098 F->insert(It, copy0MBB);
12099 F->insert(It, sinkMBB);
12102 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12108 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12124 .
addImm(
MI.getOperand(3).getImm())
12125 .
addReg(
MI.getOperand(4).getReg());
12140 .
addReg(
MI.getOperand(1).getReg())
12142 .
addReg(
MI.getOperand(2).getReg())
12145 MI.eraseFromParent();
12150 case ARM::BCCZi64: {
12156 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12161 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12165 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12171 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12175 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12185 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12194 MI.eraseFromParent();
12198 case ARM::Int_eh_sjlj_setjmp:
12199 case ARM::Int_eh_sjlj_setjmp_nofp:
12200 case ARM::tInt_eh_sjlj_setjmp:
12201 case ARM::t2Int_eh_sjlj_setjmp:
12202 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12205 case ARM::Int_eh_sjlj_setup_dispatch:
12206 EmitSjLjDispatchBlock(
MI, BB);
12208 case ARM::COPY_STRUCT_BYVAL_I32:
12210 return EmitStructByval(
MI, BB);
12211 case ARM::WIN__CHKSTK:
12212 return EmitLowered__chkstk(
MI, BB);
12213 case ARM::WIN__DBZCHK:
12214 return EmitLowered__dbzchk(
MI, BB);
12230 if (!
Node->hasAnyUseOfValue(0)) {
12231 MI.getOperand(0).setIsDead(
true);
12233 if (!
Node->hasAnyUseOfValue(1)) {
12234 MI.getOperand(1).setIsDead(
true);
12238 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12239 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12240 : &ARM::GPRRegClass);
12247 if (
MI.getOpcode() == ARM::MEMCPY) {
12268 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12269 &&
"converted opcode should be the same except for cc_out"
12270 " (and, on Thumb1, pred)");
12278 if (Subtarget->isThumb1Only()) {
12279 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12280 MI.addOperand(
MI.getOperand(1));
12281 MI.removeOperand(1);
12285 for (
unsigned i =
MI.getNumOperands(); i--;) {
12287 if (
op.isReg() &&
op.isUse()) {
12290 MI.tieOperands(DefIdx, i);
12298 ccOutIdx =
MCID->getNumOperands() - 1;
12300 ccOutIdx =
MCID->getNumOperands() - 1;
12304 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12305 assert(!NewOpc &&
"Optional cc_out operand required");
12310 bool definesCPSR =
false;
12311 bool deadCPSR =
false;
12312 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12316 definesCPSR =
true;
12319 MI.removeOperand(i);
12323 if (!definesCPSR) {
12324 assert(!NewOpc &&
"Optional cc_out operand required");
12327 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12329 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12330 "expect uninitialized optional cc_out operand");
12332 if (!Subtarget->isThumb1Only())
12368 switch (
N->getOpcode()) {
12369 default:
return false;
12371 CC =
N->getOperand(0);
12393 EVT VT =
N->getValueType(0);
12394 CC =
N->getOperand(0);
12441 EVT VT =
N->getValueType(0);
12444 bool SwapSelectOps;
12446 NonConstantVal, DAG))
12452 OtherOp, NonConstantVal);
12458 CCOp, TrueVal, FalseVal);
12478 if (
N->getOpcode() == ARMISD::VUZP)
12482 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12497 if (!
N->getValueType(0).is64BitVector())
12505 EVT VT =
N->getValueType(0);
12544 EVT VT =
N->getValueType(0);
12550 Opcode = Intrinsic::arm_neon_vpaddls;
12552 Opcode = Intrinsic::arm_neon_vpaddlu;
12580 EVT VT =
N->getValueType(0);
12595 unsigned nextIndex = 0;
12646 Ops.push_back(Vec);
12663 return DAG.
getNode(ExtOp, dl, VT, tmp);
12694 if (SRA.getOpcode() !=
ISD::SRA) {
12701 if (Const->getZExtValue() != 31)
12706 if (SRA.getOperand(0) !=
Mul)
12710 SDLoc dl(AddcNode);
12711 unsigned Opcode = 0;
12716 Opcode = ARMISD::SMLALBB;
12717 Op0 =
Mul.getOperand(0);
12718 Op1 =
Mul.getOperand(1);
12720 Opcode = ARMISD::SMLALBT;
12721 Op0 =
Mul.getOperand(0);
12722 Op1 =
Mul.getOperand(1).getOperand(0);
12724 Opcode = ARMISD::SMLALTB;
12725 Op0 =
Mul.getOperand(0).getOperand(0);
12726 Op1 =
Mul.getOperand(1);
12728 Opcode = ARMISD::SMLALTT;
12729 Op0 =
Mul->getOperand(0).getOperand(0);
12730 Op1 =
Mul->getOperand(1).getOperand(0);
12746 SDValue resNode(AddcNode, 0);
12774 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12775 "Expect an ADDE or SUBE");
12779 "ADDE node has the wrong inputs");
12783 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12784 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12785 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12786 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12798 "Expect ADDC with two result values. First: i32");
12802 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12818 bool IsLeftOperandMUL =
false;
12823 IsLeftOperandMUL =
true;
12834 SDValue *LowAddSub =
nullptr;
12837 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12840 if (IsLeftOperandMUL)
12841 HiAddSub = &AddeSubeOp1;
12843 HiAddSub = &AddeSubeOp0;
12848 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12849 LoMul = &AddcSubcOp0;
12850 LowAddSub = &AddcSubcOp1;
12852 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12853 LoMul = &AddcSubcOp1;
12854 LowAddSub = &AddcSubcOp0;
12862 if (AddcSubcNode == HiAddSub->getNode() ||
12878 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12883 Ops.push_back(*HiAddSub);
12884 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12885 FinalOpc = ARMISD::SMMLSR;
12887 FinalOpc = ARMISD::SMMLAR;
12892 return SDValue(AddeSubeNode, 0);
12893 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12899 Ops.push_back(*LowAddSub);
12900 Ops.push_back(*HiAddSub);
12913 return SDValue(AddeSubeNode, 0);
12925 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12930 if (AddcNode->
getOpcode() != ARMISD::ADDC)
12934 SDNode *UmlalNode =
nullptr;
12973 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12978 SDNode* AddcNode =
N->getOperand(2).getNode();
12979 SDNode* AddeNode =
N->getOperand(3).getNode();
12980 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
12981 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
12987 {N->getOperand(0), N->getOperand(1),
12988 AddcNode->getOperand(0), AddcNode->getOperand(1)});
12998 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13002 if (
LHS->getOpcode() == ARMISD::ADDE &&
13012 int32_t imm =
C->getSExtValue();
13013 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13016 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13018 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13033 int64_t imm =
C->getSExtValue();
13042 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13044 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13045 N->getOperand(0),
RHS,
N->getOperand(2));
13057 if (!Subtarget->hasMVEIntegerOps())
13070 SetCC =
N->getOperand(0);
13074 TrueVal =
N->getOperand(1);
13075 FalseVal =
N->getOperand(2);
13077 LHS =
N->getOperand(0);
13078 RHS =
N->getOperand(1);
13080 TrueVal =
N->getOperand(2);
13081 FalseVal =
N->getOperand(3);
13086 unsigned int Opcode = 0;
13090 Opcode = ARMISD::VMINVu;
13096 Opcode = ARMISD::VMINVs;
13102 Opcode = ARMISD::VMAXVu;
13108 Opcode = ARMISD::VMAXVs;
13115 switch (TrueVal->getOpcode()) {
13134 if (TrueVal !=
LHS || FalseVal !=
RHS)
13137 EVT LeftType =
LHS->getValueType(0);
13138 EVT RightType =
RHS->getValueType(0);
13141 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13145 if (VectorScalarType != MVT::i32)
13153 if (VectorScalarType != MVT::i32)
13166 EVT VT =
N->getValueType(0);
13174 Shft =
N->getOperand(0);
13181 Cmp.getOperand(0) !=
N->getOperand(1) ||
13182 Cmp.getOperand(1) !=
N->getOperand(2))
13184 Shft =
N->getOperand(1);
13196 ScalarType = MVT::i8;
13199 case (1 << 15) - 1:
13200 ScalarType = MVT::i16;
13203 case (1ULL << 31) - 1:
13204 ScalarType = MVT::i32;
13235 unsigned LegalLanes = 128 / (ShftAmt + 1);
13247 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13248 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13249 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13250 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13259 for (
unsigned I = 0;
I < NumParts; ++
I) {
13266 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13276 if (!Subtarget->hasMVEIntegerOps())
13291 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13301 if (!Const || !Const->isOne())
13319 EVT VT =
N->getValueType(0);
13321 if (!Subtarget->hasMVEIntegerOps() ||
13350 Opc = Intrinsic::arm_mve_vctp64;
13353 Opc = Intrinsic::arm_mve_vctp32;
13356 Opc = Intrinsic::arm_mve_vctp16;
13359 Opc = Intrinsic::arm_mve_vctp8;
13413 EVT VT =
N->getValueType(0);
13419 switch (
Op.getOpcode()) {
13421 case ARMISD::VADDVs:
13422 case ARMISD::VADDVu:
13423 case ARMISD::VMLAVs:
13424 case ARMISD::VMLAVu:
13444 unsigned N0RedOp = 0;
13451 unsigned N1RedOp = 0;
13465 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13467 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13474 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13498 if (!BaseLocDecomp0.getBase() ||
13499 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13500 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13502 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13504 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13514 if (IsBefore < 0) {
13517 }
else if (IsBefore > 0) {
13530 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13540 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13550 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13552 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13559 if (!Subtarget->hasMVEIntegerOps())
13565 EVT VT =
N->getValueType(0);
13570 if (VT != MVT::i64)
13581 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13601 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13610 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13612 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13614 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13616 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13618 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13620 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13622 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13624 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13626 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13628 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13630 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13632 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13634 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13636 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13638 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13640 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13650 "Expected shift op");
13652 SDValue ShiftLHS =
N->getOperand(0);
13666 if (Subtarget->isThumb1Only()) {
13677 if (Const->getAPIntValue().ult(256))
13680 Const->getAPIntValue().sgt(-256))
13696 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13697 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13698 "Expected XOR(SHIFT) pattern");
13703 if (XorC && ShiftC) {
13704 unsigned MaskIdx, MaskLen;
13705 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13706 unsigned ShiftAmt = ShiftC->getZExtValue();
13707 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13708 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13709 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13710 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13720 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13722 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13723 "Expected shift-shift mask");
13725 if (!Subtarget->isThumb1Only())
13728 EVT VT =
N->getValueType(0);
13736 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13738 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13743 if (!Subtarget->hasNEON()) {
13744 if (Subtarget->isThumb1Only())
13758 return Subtarget->hasVFP2Base();
13760 return Subtarget->hasVFP2Base();
13762 return Subtarget->hasFP64();
13765 return Subtarget->hasMVEFloatOps();
13794 if (ST->isThumb() && ST->isThumb1Only())
13798 for (
auto *U :
N->users()) {
13799 switch(U->getOpcode()) {
13817 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13818 U->getOperand(1).getOpcode() ==
ISD::SHL)
13828 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13835 if (!C1ShlC2 || !C2)
13838 APInt C2Int = C2->getAPIntValue();
13839 APInt C1Int = C1ShlC2->getAPIntValue();
13841 if (C2Int.
uge(C2Width))
13847 if ((C1Int & Mask) != C1Int)
13854 auto LargeImm = [](
const APInt &Imm) {
13855 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13856 return Imm.getBitWidth() - Zeros > 8;
13859 if (LargeImm(C1Int) || LargeImm(C2Int))
13871 SHL.dump();
N->dump());
13974 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
13995 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14016 if (!Subtarget->hasVMLxForwarding())
14035 EVT VT =
N->getValueType(0);
14046 EVT VT =
N->getValueType(0);
14047 if (VT != MVT::v2i64)
14058 return Op->getOperand(0);
14072 And =
And->getOperand(0);
14077 Mask = Mask->getOperand(0);
14080 Mask.getValueType() != MVT::v4i32)
14086 return And->getOperand(0);
14091 if (
SDValue Op0 = IsSignExt(N0)) {
14092 if (
SDValue Op1 = IsSignExt(N1)) {
14093 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14094 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14095 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14098 if (
SDValue Op0 = IsZeroExt(N0)) {
14099 if (
SDValue Op1 = IsZeroExt(N1)) {
14100 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14101 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14102 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14114 EVT VT =
N->getValueType(0);
14115 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14126 if (VT != MVT::i32)
14133 int64_t MulAmt =
C->getSExtValue();
14136 ShiftAmt = ShiftAmt & (32 - 1);
14141 MulAmt >>= ShiftAmt;
14202 if (
N->getValueType(0) != MVT::i32)
14211 if (C1 == 255 || C1 == 65535)
14214 SDNode *N0 =
N->getOperand(0).getNode();
14228 if (!C2 || C2 >= 32)
14272 if (Trailing == C2 && C2 + C3 < 32) {
14285 if (Leading == C2 && C2 + C3 < 32) {
14313 EVT VT =
N->getValueType(0);
14317 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14320 APInt SplatBits, SplatUndef;
14321 unsigned SplatBitSize;
14323 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14324 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14325 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14326 SplatBitSize == 64) {
14333 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14335 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14360 if (!Subtarget->hasV6Ops() ||
14361 (Subtarget->isThumb() &&
14362 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14365 SDValue SRL = OR->getOperand(0);
14366 SDValue SHL = OR->getOperand(1);
14369 SRL = OR->getOperand(1);
14370 SHL = OR->getOperand(0);
14377 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14381 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14382 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14383 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14402 unsigned Opcode = 0;
14403 if (
isS16(OpS16, DAG))
14404 Opcode = ARMISD::SMULWB;
14406 Opcode = ARMISD::SMULWT;
14421 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14424 EVT VT =
N->getValueType(0);
14439 if (VT != MVT::i32)
14452 if (Mask == 0xffff)
14459 if ((Val & ~Mask) != Val)
14465 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14484 (Mask == ~Mask2)) {
14487 if (Subtarget->hasDSP() &&
14488 (Mask == 0xffff || Mask == 0xffff0000))
14494 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14501 (~Mask == Mask2)) {
14504 if (Subtarget->hasDSP() &&
14505 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14561 if (
N->getOpcode() == ARMISD::VCMP)
14563 else if (
N->getOpcode() == ARMISD::VCMPZ)
14571 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14578 EVT VT =
N->getValueType(0);
14583 auto IsFreelyInvertable = [&](
SDValue V) {
14584 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14590 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14608 if (AndOp.getOpcode() !=
ISD::AND)
14612 SDValue Mask = AndOp.getOperand(1);
14622 bool IsShiftRight =
false;
14625 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14626 IsShiftRight =
true;
14629 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14637 APInt RequiredMask = IsShiftRight
14640 if (MaskBits != RequiredMask)
14643 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14653 EVT VT =
N->getValueType(0);
14659 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14660 VT == MVT::v8i1 || VT == MVT::v16i1))
14663 APInt SplatBits, SplatUndef;
14664 unsigned SplatBitSize;
14666 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14667 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14668 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14669 SplatBitSize == 64) {
14676 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14678 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14698 (Subtarget->hasMVEIntegerOps() &&
14699 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14702 return ShiftInsert;
14706 return ShiftInsert;
14720 unsigned SplatBitSize;
14723 APInt SplatBits0, SplatBits1;
14727 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14728 HasAnyUndefs) && !HasAnyUndefs) {
14729 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14730 HasAnyUndefs) && !HasAnyUndefs) {
14735 SplatBits0 == ~SplatBits1) {
14743 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14765 EVT VT =
N->getValueType(0);
14780 if (Subtarget->hasMVEIntegerOps()) {
14808 assert(
N->getOpcode() == ARMISD::BFI);
14811 ToMask =
~N->getConstantOperandAPInt(2);
14831 unsigned LastActiveBitInA =
A.countr_zero();
14832 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14833 return LastActiveBitInA - 1 == FirstActiveBitInB;
14838 APInt ToMask, FromMask;
14843 if (V.getOpcode() != ARMISD::BFI)
14846 APInt NewToMask, NewFromMask;
14848 if (NewFrom != From)
14852 if ((NewToMask & ToMask).getBoolValue())
14877 unsigned InvMask =
N->getConstantOperandVal(2);
14881 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14882 "undefined behavior");
14883 unsigned Mask = (1u << Width) - 1;
14885 if ((Mask & (~Mask2)) == 0)
14887 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14894 APInt ToMask1, FromMask1;
14897 APInt ToMask2, FromMask2;
14903 APInt NewFromMask = FromMask1 | FromMask2;
14904 APInt NewToMask = ToMask1 | ToMask2;
14906 EVT VT =
N->getValueType(0);
14909 if (NewFromMask[0] == 0)
14912 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
14920 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
14921 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14922 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14924 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14928 EVT VT =
N->getValueType(0);
14931 N->getOperand(1),
N->getOperand(2));
14943 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
14945 SDValue CSInc = Cmp->getOperand(0);
14955 if (CSInc.
getOpcode() == ARMISD::CSINC &&
14995 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
14996 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
14999 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15001 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15014 SDValue InDouble =
N->getOperand(0);
15015 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15029 SDValue BasePtr = LD->getBasePtr();
15031 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15032 LD->getAlign(), LD->getMemOperand()->getFlags());
15038 LD->getPointerInfo().getWithOffset(4),
15040 LD->getMemOperand()->getFlags());
15059 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15073 if (!Subtarget->
isLittle() && BVSwap)
15091 if (!Subtarget->
isLittle() && BVSwap)
15110 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15123 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15136 if (Copy.getValueType() == MVT::f32 &&
15138 bool HasGlue = Copy->getNumOperands() == 3;
15139 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15140 HasGlue ? Copy->getOperand(2) :
SDValue()};
15141 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15160 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15161 LN0->getMemoryVT() == MVT::i16) {
15164 LN0->getBasePtr(), LN0->getMemOperand());
15182 EVT VT =
N->getValueType(0);
15216 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15217 for (
unsigned i = 0; i < NumElts; ++i) {
15218 SDNode *Elt =
N->getOperand(i).getNode();
15235 if (
N->getNumOperands() == 2)
15241 EVT VT =
N->getValueType(0);
15247 for (
unsigned i = 0; i < NumElts; ++i) {
15273 EVT VT =
N->getValueType(0);
15281 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15286 Use->getValueType(0).isFloatingPoint())
15294 unsigned NumOfBitCastedElts = 0;
15296 unsigned NumOfRelevantElts = NumElts;
15297 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15302 ++NumOfBitCastedElts;
15306 --NumOfRelevantElts;
15310 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15328 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15333 V->getOperand(0).getValueType() == MVT::i32)
15335 V = V.getOperand(0);
15352 EVT VT =
N->getValueType(0);
15357 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15359 if (
Op->getOperand(0).getValueType() == VT)
15360 return Op->getOperand(0);
15361 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15368 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15375 if (
Op.getValueType() == MVT::i32) {
15386 EVT VT =
N->getValueType(0);
15391 if (ST->isLittle())
15395 if (
Op.getValueType() == VT)
15402 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15404 if (
Op->getOperand(0).getValueType() == VT)
15405 return Op->getOperand(0);
15406 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15414 if (!Subtarget->hasMVEIntegerOps())
15417 EVT VT =
N->getValueType(0);
15425 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15431 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15435 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15448 EVT VT =
N->getValueType(0);
15449 SDNode *Elt =
N->getOperand(1).getNode();
15464 Vec, V,
N->getOperand(2));
15474 EVT VT =
N->getValueType(0);
15502 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15503 isa<ConstantSDNode>(V->getOperand(1)) &&
15504 V->getConstantOperandVal(1) == Lane + 1 &&
15505 V->getOperand(0).getResNo() == ResNo;
15507 if (OtherIt == Op0->
users().
end())
15512 SDValue OtherExt(*OtherIt, 0);
15524 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15527 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15537 EVT VT =
N->getValueType(0);
15541 if (Op0->
getOpcode() == ARMISD::VDUP) {
15543 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15544 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15545 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15546 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15547 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15550 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15551 X =
X->getOperand(0);
15552 if (
X.getValueType() == VT)
15560 return Op0.
getOperand(
N->getConstantOperandVal(1));
15570 unsigned Offset =
N->getConstantOperandVal(1);
15572 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15582 unsigned Idx =
N->getConstantOperandVal(1);
15596 EVT VT =
N->getValueType(0);
15599 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15601 Op.getOperand(0).getValueType().getScalarType())
15602 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15611 SDValue SubVec =
N->getOperand(1);
15612 uint64_t IdxVal =
N->getConstantOperandVal(2);
15623 if (IdxVal == 0 && Vec.
isUndef())
15629 (IdxVal != 0 && IdxVal != NumSubElts))
15660 ARMISD::VMOVN,
DL, VT,
15666 ARMISD::VMOVN,
DL, VT,
15702 EVT VT =
N->getValueType(0);
15713 unsigned HalfElts = NumElts/2;
15715 for (
unsigned n = 0; n < NumElts; ++n) {
15718 if (MaskElt < (
int)HalfElts)
15720 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15721 NewElt = HalfElts + MaskElt - NumElts;
15764 bool SimpleConstIncOnly,
15772 bool isLoadOp =
true;
15773 bool isLaneOp =
false;
15776 bool hasAlignment =
true;
15777 unsigned NewOpc = 0;
15778 unsigned NumVecs = 0;
15779 if (
Target.isIntrinsic) {
15780 unsigned IntNo =
N->getConstantOperandVal(1);
15784 case Intrinsic::arm_neon_vld1:
15788 case Intrinsic::arm_neon_vld2:
15792 case Intrinsic::arm_neon_vld3:
15796 case Intrinsic::arm_neon_vld4:
15800 case Intrinsic::arm_neon_vld1x2:
15803 hasAlignment =
false;
15805 case Intrinsic::arm_neon_vld1x3:
15808 hasAlignment =
false;
15810 case Intrinsic::arm_neon_vld1x4:
15813 hasAlignment =
false;
15815 case Intrinsic::arm_neon_vld2dup:
15819 case Intrinsic::arm_neon_vld3dup:
15823 case Intrinsic::arm_neon_vld4dup:
15827 case Intrinsic::arm_neon_vld2lane:
15832 case Intrinsic::arm_neon_vld3lane:
15837 case Intrinsic::arm_neon_vld4lane:
15842 case Intrinsic::arm_neon_vst1:
15847 case Intrinsic::arm_neon_vst2:
15848 NewOpc = ARMISD::VST2_UPD;
15852 case Intrinsic::arm_neon_vst3:
15857 case Intrinsic::arm_neon_vst4:
15858 NewOpc = ARMISD::VST4_UPD;
15862 case Intrinsic::arm_neon_vst2lane:
15868 case Intrinsic::arm_neon_vst3lane:
15874 case Intrinsic::arm_neon_vst4lane:
15880 case Intrinsic::arm_neon_vst1x2:
15884 hasAlignment =
false;
15886 case Intrinsic::arm_neon_vst1x3:
15890 hasAlignment =
false;
15892 case Intrinsic::arm_neon_vst1x4:
15896 hasAlignment =
false;
15901 switch (
N->getOpcode()) {
15937 VecTy =
N->getValueType(0);
15938 }
else if (
Target.isIntrinsic) {
15939 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
15942 "Node has to be a load, a store, or an intrinsic!");
15943 VecTy =
N->getOperand(1).getValueType();
15951 if (isLaneOp || isVLDDUPOp)
15954 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
15960 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
15969 EVT AlignedVecTy = VecTy;
15989 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
15990 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16001 Alignment =
Align(1);
16007 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16009 for (n = 0; n < NumResultVecs; ++n)
16010 Tys[n] = AlignedVecTy;
16011 Tys[n++] = MVT::i32;
16012 Tys[n] = MVT::Other;
16017 Ops.push_back(
N->getOperand(0));
16018 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16023 Ops.push_back(StN->getValue());
16027 unsigned LastOperand =
16028 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16029 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16030 Ops.push_back(
N->getOperand(i));
16038 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16049 for (
unsigned i = 0; i < NumResultVecs; ++i)
16054 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16055 SDValue &LdVal = NewResults[0];
16091 switch (
N->getOpcode()) {
16095 *Ptr =
N->getOperand(0);
16096 *CInc =
N->getOperand(1);
16103 *Ptr =
N->getOperand(1);
16104 *CInc =
N->getOperand(2);
16131 SDValue Addr =
N->getOperand(AddrOpIdx);
16142 unsigned ConstInc =
16147 if (BaseUpdates.
size() >= MaxBaseUpdates)
16167 unsigned UserOffset =
16170 if (!UserOffset || UserOffset <=
Offset)
16173 unsigned NewConstInc = UserOffset -
Offset;
16176 if (BaseUpdates.
size() >= MaxBaseUpdates)
16183 unsigned NumValidUpd = BaseUpdates.
size();
16184 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16195 return LHS.ConstInc <
RHS.ConstInc;
16224 unsigned IntNo =
N->getConstantOperandVal(1);
16225 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16227 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16250 bool isLoadOp =
true;
16251 unsigned NewOpc = 0;
16252 unsigned NumVecs = 0;
16256 case Intrinsic::arm_mve_vld2q:
16260 case Intrinsic::arm_mve_vld4q:
16264 case Intrinsic::arm_mve_vst2q:
16265 NewOpc = ARMISD::VST2_UPD;
16269 case Intrinsic::arm_mve_vst4q:
16270 NewOpc = ARMISD::VST4_UPD;
16279 VecTy =
N->getValueType(0);
16281 VecTy =
N->getOperand(3).getValueType();
16295 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16297 for (n = 0; n < NumResultVecs; ++n)
16299 Tys[n++] = MVT::i32;
16300 Tys[n] = MVT::Other;
16305 Ops.push_back(
N->getOperand(0));
16306 Ops.push_back(
N->getOperand(2));
16307 Ops.push_back(Inc);
16309 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16310 Ops.push_back(
N->getOperand(i));
16317 for (
unsigned i = 0; i < NumResultVecs; ++i)
16336 EVT VT =
N->getValueType(0);
16342 SDNode *VLD =
N->getOperand(0).getNode();
16345 unsigned NumVecs = 0;
16346 unsigned NewOpc = 0;
16348 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16351 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16354 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16366 if (
Use.getResNo() == NumVecs)
16369 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16370 VLDLaneNo !=
User->getConstantOperandVal(1))
16377 for (n = 0; n < NumVecs; ++n)
16379 Tys[n] = MVT::Other;
16389 unsigned ResNo =
Use.getResNo();
16391 if (ResNo == NumVecs)
16398 std::vector<SDValue> VLDDupResults;
16399 for (
unsigned n = 0; n < NumVecs; ++n)
16413 EVT VT =
N->getValueType(0);
16416 if (Subtarget->hasMVEIntegerOps()) {
16420 ExtractVT = MVT::i32;
16422 N->getOperand(0),
N->getOperand(1));
16434 Op =
Op.getOperand(0);
16435 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16439 unsigned EltSize =
Op.getScalarValueSizeInBits();
16441 unsigned Imm =
Op.getConstantOperandVal(0);
16457 if (Subtarget->hasMVEIntegerOps()) {
16460 if (
Op.getValueType() == MVT::f32)
16461 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16463 else if (
Op.getValueType() == MVT::f16)
16464 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16465 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16468 if (!Subtarget->hasNEON())
16475 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16476 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16477 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16482 LD->getMemoryVT(), LD->getMemOperand());
16493 EVT VT =
N->getValueType(0);
16515 assert(StVT != VT &&
"Cannot truncate to the same type");
16525 if (0 != (NumElems * FromEltSz) % ToEltSz)
16528 unsigned SizeRatio = FromEltSz / ToEltSz;
16533 NumElems * SizeRatio);
16539 for (
unsigned i = 0; i < NumElems; ++i)
16553 MVT StoreType = MVT::i8;
16555 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16575 for (
unsigned I = 0;
I <
E;
I++) {
16606 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16609 unsigned NumElements = 4;
16626 unsigned Off0 = Rev ? NumElts : 0;
16627 unsigned Off1 = Rev ? 0 : NumElts;
16629 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16630 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16632 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16640 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16660 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16671 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16675 NewToVT, Alignment, MMOFlags, AAInfo);
16708 unsigned NewOffset =
16716 NewToVT, Alignment, MMOFlags, AAInfo);
16738 {Extract.getOperand(0), Extract.getOperand(1)});
16769 if (Subtarget->hasNEON())
16773 if (Subtarget->hasMVEFloatOps())
16777 if (Subtarget->hasMVEIntegerOps()) {
16852 if (!Subtarget->hasNEON())
16856 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16864 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16866 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16867 uint32_t IntBits = IntTy.getSizeInBits();
16868 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16869 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16880 if (
C == -1 ||
C == 0 ||
C > 32)
16885 unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16886 Intrinsic::arm_neon_vcvtfp2fxu;
16889 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16892 if (IntBits < FloatBits)
16900 if (!Subtarget->hasMVEFloatOps())
16908 EVT VT =
N->getValueType(0);
16913 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16915 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
16917 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16918 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16920 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16933 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
16944 EVT VT =
N->getValueType(0);
16947 if (!
N->getFlags().hasAllowReassociation())
16954 unsigned Opc =
A.getConstantOperandVal(0);
16955 if (
Opc != Intrinsic::arm_mve_vcmlaq)
16960 A.getOperand(3),
A.getOperand(4));
16992 if (!Subtarget->hasNEON())
16996 unsigned OpOpcode =
Op.getNode()->getOpcode();
16997 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17001 SDValue ConstVec =
N->getOperand(1);
17005 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17007 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17008 uint32_t IntBits = IntTy.getSizeInBits();
17009 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17010 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17030 int32_t
C = IntVal.exactLogBase2();
17031 if (
C == -1 ||
C == 0 ||
C > 32)
17037 if (IntBits < FloatBits)
17039 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17041 unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17042 : Intrinsic::arm_neon_vcvtfxu2fp;
17050 if (!ST->hasMVEIntegerOps())
17054 EVT ResVT =
N->getValueType(0);
17082 EVT AVT =
A.getValueType();
17088 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17089 EVT AVT =
A.getValueType();
17099 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17100 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17103 if (ExtTypeMatches(
A, ExtTypes))
17104 return ExtendIfNeeded(
A, ExtendCode);
17107 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17117 if (ExtTypeMatches(
A, ExtTypes))
17118 return ExtendIfNeeded(
A, ExtendCode);
17121 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17131 if (ResVT != RetTy)
17134 if (
Mul->getOpcode() == ExtendCode &&
17135 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17137 Mul =
Mul->getOperand(0);
17146 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17147 A = ExtendIfNeeded(
A, ExtendCode);
17148 B = ExtendIfNeeded(
B, ExtendCode);
17153 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17166 if (
Mul->getOpcode() == ExtendCode &&
17167 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17169 Mul =
Mul->getOperand(0);
17178 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17179 A = ExtendIfNeeded(
A, ExtendCode);
17180 B = ExtendIfNeeded(
B, ExtendCode);
17191 EVT VT =
Ops[0].getValueType();
17192 if (VT == MVT::v16i8) {
17193 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17194 "Unexpected illegal long reduction opcode");
17195 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17207 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17220 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17222 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17223 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17225 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17226 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17228 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17231 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17234 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17238 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17241 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17244 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17247 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17250 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17253 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17256 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17258 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17260 return Create64bitNode(ARMISD::VADDLVs, {
A});
17262 return Create64bitNode(ARMISD::VADDLVu, {
A});
17265 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17268 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17271 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17273 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17275 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17277 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17280 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17283 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17290 Op =
Op->getOperand(1);
17292 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17294 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17311 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17313 if (!Shuf || !Shuf->getOperand(1).isUndef())
17318 APInt SetElts(Mask.size(), 0);
17319 for (
int E : Mask) {
17327 if (
N->getNumOperands() != VecOp + 1) {
17329 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17335 if (
Op.getValueType().isVector())
17336 Ops.push_back(
Op.getOperand(0));
17347 unsigned IsTop =
N->getConstantOperandVal(2);
17354 if (Op0->
isUndef() && !IsTop)
17359 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17360 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17368 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17370 APInt Op0DemandedElts =
17371 IsTop ? Op1DemandedElts
17386 unsigned IsTop =
N->getConstantOperandVal(2);
17388 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17389 APInt Op0DemandedElts =
17401 EVT VT =
N->getValueType(0);
17408 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17409 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17413 LHS.getOperand(0),
RHS.getOperand(0));
17428 int ShiftAmt =
C->getSExtValue();
17429 if (ShiftAmt == 0) {
17435 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17436 unsigned NewOpcode =
17437 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17452 unsigned IntNo =
N->getConstantOperandVal(0);
17463 case Intrinsic::arm_neon_vshifts:
17464 case Intrinsic::arm_neon_vshiftu:
17465 case Intrinsic::arm_neon_vrshifts:
17466 case Intrinsic::arm_neon_vrshiftu:
17467 case Intrinsic::arm_neon_vrshiftn:
17468 case Intrinsic::arm_neon_vqshifts:
17469 case Intrinsic::arm_neon_vqshiftu:
17470 case Intrinsic::arm_neon_vqshiftsu:
17471 case Intrinsic::arm_neon_vqshiftns:
17472 case Intrinsic::arm_neon_vqshiftnu:
17473 case Intrinsic::arm_neon_vqshiftnsu:
17474 case Intrinsic::arm_neon_vqrshiftns:
17475 case Intrinsic::arm_neon_vqrshiftnu:
17476 case Intrinsic::arm_neon_vqrshiftnsu: {
17477 EVT VT =
N->getOperand(1).getValueType();
17479 unsigned VShiftOpc = 0;
17482 case Intrinsic::arm_neon_vshifts:
17483 case Intrinsic::arm_neon_vshiftu:
17485 VShiftOpc = ARMISD::VSHLIMM;
17488 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17489 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17490 : ARMISD::VSHRuIMM);
17495 case Intrinsic::arm_neon_vrshifts:
17496 case Intrinsic::arm_neon_vrshiftu:
17501 case Intrinsic::arm_neon_vqshifts:
17502 case Intrinsic::arm_neon_vqshiftu:
17507 case Intrinsic::arm_neon_vqshiftsu:
17512 case Intrinsic::arm_neon_vrshiftn:
17513 case Intrinsic::arm_neon_vqshiftns:
17514 case Intrinsic::arm_neon_vqshiftnu:
17515 case Intrinsic::arm_neon_vqshiftnsu:
17516 case Intrinsic::arm_neon_vqrshiftns:
17517 case Intrinsic::arm_neon_vqrshiftnu:
17518 case Intrinsic::arm_neon_vqrshiftnsu:
17530 case Intrinsic::arm_neon_vshifts:
17531 case Intrinsic::arm_neon_vshiftu:
17534 case Intrinsic::arm_neon_vrshifts:
17535 VShiftOpc = ARMISD::VRSHRsIMM;
17537 case Intrinsic::arm_neon_vrshiftu:
17538 VShiftOpc = ARMISD::VRSHRuIMM;
17540 case Intrinsic::arm_neon_vrshiftn:
17541 VShiftOpc = ARMISD::VRSHRNIMM;
17543 case Intrinsic::arm_neon_vqshifts:
17544 VShiftOpc = ARMISD::VQSHLsIMM;
17546 case Intrinsic::arm_neon_vqshiftu:
17547 VShiftOpc = ARMISD::VQSHLuIMM;
17549 case Intrinsic::arm_neon_vqshiftsu:
17550 VShiftOpc = ARMISD::VQSHLsuIMM;
17552 case Intrinsic::arm_neon_vqshiftns:
17553 VShiftOpc = ARMISD::VQSHRNsIMM;
17555 case Intrinsic::arm_neon_vqshiftnu:
17556 VShiftOpc = ARMISD::VQSHRNuIMM;
17558 case Intrinsic::arm_neon_vqshiftnsu:
17559 VShiftOpc = ARMISD::VQSHRNsuIMM;
17561 case Intrinsic::arm_neon_vqrshiftns:
17562 VShiftOpc = ARMISD::VQRSHRNsIMM;
17564 case Intrinsic::arm_neon_vqrshiftnu:
17565 VShiftOpc = ARMISD::VQRSHRNuIMM;
17567 case Intrinsic::arm_neon_vqrshiftnsu:
17568 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17573 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17574 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17577 case Intrinsic::arm_neon_vshiftins: {
17578 EVT VT =
N->getOperand(1).getValueType();
17580 unsigned VShiftOpc = 0;
17583 VShiftOpc = ARMISD::VSLIIMM;
17584 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17585 VShiftOpc = ARMISD::VSRIIMM;
17591 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17592 N->getOperand(1),
N->getOperand(2),
17596 case Intrinsic::arm_neon_vqrshifts:
17597 case Intrinsic::arm_neon_vqrshiftu:
17601 case Intrinsic::arm_neon_vbsl: {
17603 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17604 N->getOperand(2),
N->getOperand(3));
17606 case Intrinsic::arm_mve_vqdmlah:
17607 case Intrinsic::arm_mve_vqdmlash:
17608 case Intrinsic::arm_mve_vqrdmlah:
17609 case Intrinsic::arm_mve_vqrdmlash:
17610 case Intrinsic::arm_mve_vmla_n_predicated:
17611 case Intrinsic::arm_mve_vmlas_n_predicated:
17612 case Intrinsic::arm_mve_vqdmlah_predicated:
17613 case Intrinsic::arm_mve_vqdmlash_predicated:
17614 case Intrinsic::arm_mve_vqrdmlah_predicated:
17615 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17620 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17627 case Intrinsic::arm_mve_minv:
17628 case Intrinsic::arm_mve_maxv:
17629 case Intrinsic::arm_mve_minav:
17630 case Intrinsic::arm_mve_maxav:
17631 case Intrinsic::arm_mve_minv_predicated:
17632 case Intrinsic::arm_mve_maxv_predicated:
17633 case Intrinsic::arm_mve_minav_predicated:
17634 case Intrinsic::arm_mve_maxav_predicated: {
17637 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17644 case Intrinsic::arm_mve_addv: {
17647 bool Unsigned =
N->getConstantOperandVal(2);
17648 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17652 case Intrinsic::arm_mve_addlv:
17653 case Intrinsic::arm_mve_addlv_predicated: {
17656 bool Unsigned =
N->getConstantOperandVal(2);
17657 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17658 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17659 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17662 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17664 Ops.push_back(
N->getOperand(i));
17685 EVT VT =
N->getValueType(0);
17687 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17688 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17689 N->getOperand(0)->hasOneUse()) {
17706 if (AndMask == 255 || AndMask == 65535)
17710 if (MaskedBits > ShiftAmt) {
17725 if (ST->hasMVEIntegerOps())
17730 switch (
N->getOpcode()) {
17736 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17743 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17744 unsigned VShiftOpc =
17745 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17747 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17763 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17766 EVT FromVT = LD->getValueType(0);
17767 EVT ToVT =
N->getValueType(0);
17774 unsigned NumElements = 0;
17775 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17777 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17779 if (NumElements == 0 ||
17789 SDValue BasePtr = LD->getBasePtr();
17790 Align Alignment = LD->getBaseAlign();
17811 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17812 Alignment, MMOFlags, AAInfo);
17818 if (FromEltVT == MVT::f16) {
17821 for (
unsigned i = 0; i < Loads.
size(); i++) {
17823 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
17847 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17851 EVT VT =
N->getValueType(0);
17855 if (VT == MVT::i32 &&
17856 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17861 switch (
N->getOpcode()) {
17864 Opc = ARMISD::VGETLANEs;
17868 Opc = ARMISD::VGETLANEu;
17875 if (ST->hasMVEIntegerOps())
17884 if (ST->hasMVEFloatOps())
17895 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17899 EVT VT =
Op.getValueType();
17902 if (VT != MVT::i32 ||
17915 APInt MaxC = Max.getConstantOperandAPInt(1);
17918 !(MinC + 1).isPowerOf2())
17936 EVT VT =
N->getValueType(0);
17939 if (VT == MVT::i32)
17942 if (!ST->hasMVEIntegerOps())
17948 if (VT != MVT::v4i32 && VT != MVT::v8i16)
17951 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
17959 if (VT == MVT::v4i32)
17960 SaturateC =
APInt(32, (1 << 15) - 1,
true);
17962 SaturateC =
APInt(16, (1 << 7) - 1,
true);
17969 MaxC != ~SaturateC)
17974 if (IsSignedSaturate(
N, N0.
getNode())) {
17977 if (VT == MVT::v4i32) {
17978 HalfVT = MVT::v8i16;
17979 ExtVT = MVT::v4i16;
17981 HalfVT = MVT::v16i8;
17996 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18002 if (VT == MVT::v4i32)
18003 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18005 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18014 if (IsUnsignedSaturate(
N)) {
18018 if (VT == MVT::v4i32) {
18019 HalfVT = MVT::v8i16;
18020 ExtConst = 0x0000FFFF;
18022 HalfVT = MVT::v16i8;
18044 const APInt *CV = &
C->getAPIntValue();
18062 SDValue Op0 = CMOV->getOperand(0);
18063 SDValue Op1 = CMOV->getOperand(1);
18064 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
18065 SDValue CmpZ = CMOV->getOperand(3);
18101 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18108 if ((OrCI & Known.
Zero) != OrCI)
18114 EVT VT =
X.getValueType();
18115 unsigned BitInX = AndC->
logBase2();
18123 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18124 BitInY < NumActiveBits; ++BitInY) {
18125 if (OrCI[BitInY] == 0)
18128 Mask.setBit(BitInY);
18129 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18145 switch (
N->getOpcode()) {
18160 if (Const->isZero())
18162 else if (Const->isOne())
18170 unsigned IntOp =
N.getConstantOperandVal(1);
18171 if (IntOp != Intrinsic::test_start_loop_iterations &&
18172 IntOp != Intrinsic::loop_decrement_reg)
18198 bool Negate =
false;
18204 Cond =
N->getOperand(1);
18205 Dest =
N->getOperand(2);
18209 Cond =
N->getOperand(2);
18210 Dest =
N->getOperand(4);
18212 if (!Const->isOne() && !Const->isZero())
18214 Imm = Const->getZExtValue();
18242 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18243 "unsupported condition");
18248 unsigned IntOp =
Int->getConstantOperandVal(1);
18249 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18250 "expected single br user");
18251 SDNode *Br = *
N->user_begin();
18261 if (IntOp == Intrinsic::test_start_loop_iterations) {
18263 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18265 if (IsTrueIfZero(CC, Imm)) {
18267 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18271 UpdateUncondBr(Br, Dest, DAG);
18273 SDValue Ops[] = {Chain, Setup, OtherTarget};
18274 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18286 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18290 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18294 if (
Target == OtherTarget)
18295 UpdateUncondBr(Br, Dest, DAG);
18301 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18310 if (Cmp.getOpcode() != ARMISD::CMPZ)
18315 SDValue LHS = Cmp.getOperand(0);
18316 SDValue RHS = Cmp.getOperand(1);
18325 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18326 LHS->getOperand(0)->hasOneUse() &&
18330 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18342 if (Cmp.getOpcode() != ARMISD::CMPZ)
18346 EVT VT =
N->getValueType(0);
18348 SDValue LHS = Cmp.getOperand(0);
18349 SDValue RHS = Cmp.getOperand(1);
18350 SDValue FalseVal =
N->getOperand(0);
18351 SDValue TrueVal =
N->getOperand(1);
18356 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18380 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18381 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18382 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18385 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18390 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18393 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18394 LHS->getOperand(2), LHS->getOperand(3));
18404 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18408 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18410 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18419 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18452 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18464 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18484 const APInt *TrueConst;
18485 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18486 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18487 FalseVal.getOperand(1) == RHS) ||
18491 unsigned ShiftAmount = TrueConst->
logBase2();
18506 if (Known.
Zero == 0xfffffffe)
18509 else if (Known.
Zero == 0xffffff00)
18512 else if (Known.
Zero == 0xffff0000)
18525 EVT DstVT =
N->getValueType(0);
18528 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18529 EVT SrcVT = Src.getValueType();
18531 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18536 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18537 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18538 Src.getValueType().getScalarSizeInBits())
18539 Src = Src.getOperand(0);
18543 EVT SrcVT = Src.getValueType();
18544 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18545 Src.getOpcode() == ARMISD::VMVNIMM ||
18546 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18549 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18563 EVT VT =
N->getValueType(0);
18571 if (
N->getNumOperands() == 2 &&
18575 N->getOperand(0).getOperand(1),
18576 N->getOperand(1).getOperand(0),
18577 N->getOperand(1).getOperand(1));
18580 if (
N->getNumOperands() == 2 &&
18586 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18587 S0->getOperand(1) ==
S1->getOperand(1)) {
18590 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18594 ARMISD::VMOVN,
DL, VT,
18595 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18596 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18600 ARMISD::VMOVN,
DL, VT,
18601 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18602 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18610 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18611 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18612 (Op.getOpcode() == ISD::BITCAST &&
18613 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18616 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18618 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18636 int NumIns =
N->getNumOperands();
18637 assert((NumIns == 2 || NumIns == 4) &&
18638 "Expected 2 or 4 inputs to an MVETrunc");
18640 if (
N->getNumOperands() == 4)
18644 for (
int I = 0;
I < NumIns;
I++) {
18646 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18651 Ptr, MPI, StoreVT,
Align(4));
18666 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18669 EVT FromVT = LD->getMemoryVT();
18670 EVT ToVT =
N->getValueType(0);
18677 unsigned NumElements = 0;
18678 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18680 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18682 assert(NumElements != 0);
18688 LD->getExtensionType() != NewExtType)
18695 SDValue BasePtr = LD->getBasePtr();
18696 Align Alignment = LD->getBaseAlign();
18715 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18716 Alignment, MMOFlags, AAInfo);
18732 EVT VT =
N->getValueType(0);
18734 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18735 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18737 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18739 auto Extend = [&](
SDValue V) {
18748 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
18749 SDValue Ext = Extend(
N->getOperand(0));
18757 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18758 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
18762 auto CheckInregMask = [&](
int Start,
int Offset) {
18764 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18770 if (CheckInregMask(0, 0))
18772 else if (CheckInregMask(0, 1))
18773 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18774 else if (CheckInregMask(0, Mask.size()))
18776 else if (CheckInregMask(0, Mask.size() + 1))
18777 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18782 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18786 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18793 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
18804 int NumOuts =
N->getNumValues();
18805 assert((NumOuts == 2 || NumOuts == 4) &&
18806 "Expected 2 or 4 outputs to an MVEEXT");
18807 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18809 if (
N->getNumOperands() == 4)
18815 StackPtr, MPI,
Align(4));
18818 for (
int I = 0;
I < NumOuts;
I++) {
18820 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18821 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18826 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
18835 switch (
N->getOpcode()) {
18895 case ARMISD::BRCOND:
18899 case ARMISD::CSINC:
18900 case ARMISD::CSINV:
18901 case ARMISD::CSNEG:
18914 case ARMISD::PREDICATE_CAST:
18916 case ARMISD::VECTOR_REG_CAST:
18927 case ARMISD::VADDVs:
18928 case ARMISD::VADDVu:
18929 case ARMISD::VADDLVs:
18930 case ARMISD::VADDLVu:
18931 case ARMISD::VADDLVAs:
18932 case ARMISD::VADDLVAu:
18933 case ARMISD::VMLAVs:
18934 case ARMISD::VMLAVu:
18935 case ARMISD::VMLALVs:
18936 case ARMISD::VMLALVu:
18937 case ARMISD::VMLALVAs:
18938 case ARMISD::VMLALVAu:
18940 case ARMISD::VMOVN:
18942 case ARMISD::VQMOVNs:
18943 case ARMISD::VQMOVNu:
18945 case ARMISD::VQDMULH:
18951 case ARMISD::SMULWB: {
18952 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18958 case ARMISD::SMULWT: {
18959 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18965 case ARMISD::SMLALBB:
18966 case ARMISD::QADD16b:
18967 case ARMISD::QSUB16b:
18968 case ARMISD::UQADD16b:
18969 case ARMISD::UQSUB16b: {
18970 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
18977 case ARMISD::SMLALBT: {
18978 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
18980 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
18987 case ARMISD::SMLALTB: {
18988 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
18990 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
18997 case ARMISD::SMLALTT: {
18998 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19005 case ARMISD::QADD8b:
19006 case ARMISD::QSUB8b:
19007 case ARMISD::UQADD8b:
19008 case ARMISD::UQSUB8b: {
19009 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19017 if (
N->getOperand(1) ==
N->getOperand(2))
19018 return N->getOperand(1);
19022 switch (
N->getConstantOperandVal(1)) {
19023 case Intrinsic::arm_neon_vld1:
19024 case Intrinsic::arm_neon_vld1x2:
19025 case Intrinsic::arm_neon_vld1x3:
19026 case Intrinsic::arm_neon_vld1x4:
19027 case Intrinsic::arm_neon_vld2:
19028 case Intrinsic::arm_neon_vld3:
19029 case Intrinsic::arm_neon_vld4:
19030 case Intrinsic::arm_neon_vld2lane:
19031 case Intrinsic::arm_neon_vld3lane:
19032 case Intrinsic::arm_neon_vld4lane:
19033 case Intrinsic::arm_neon_vld2dup:
19034 case Intrinsic::arm_neon_vld3dup:
19035 case Intrinsic::arm_neon_vld4dup:
19036 case Intrinsic::arm_neon_vst1:
19037 case Intrinsic::arm_neon_vst1x2:
19038 case Intrinsic::arm_neon_vst1x3:
19039 case Intrinsic::arm_neon_vst1x4:
19040 case Intrinsic::arm_neon_vst2:
19041 case Intrinsic::arm_neon_vst3:
19042 case Intrinsic::arm_neon_vst4:
19043 case Intrinsic::arm_neon_vst2lane:
19044 case Intrinsic::arm_neon_vst3lane:
19045 case Intrinsic::arm_neon_vst4lane:
19047 case Intrinsic::arm_mve_vld2q:
19048 case Intrinsic::arm_mve_vld4q:
19049 case Intrinsic::arm_mve_vst2q:
19050 case Intrinsic::arm_mve_vst4q:
19067 unsigned *
Fast)
const {
19073 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19076 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19078 if (AllowsUnaligned) {
19080 *
Fast = Subtarget->hasV7Ops();
19085 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19089 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19096 if (!Subtarget->hasMVEIntegerOps())
19100 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19101 Ty == MVT::v2i1)) {
19109 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19125 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19126 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19127 Ty == MVT::v2f64) {
19138 const AttributeList &FuncAttributes)
const {
19140 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19141 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19143 if (
Op.size() >= 16 &&
19149 }
else if (
Op.size() >= 8 &&
19166 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19168 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19170 return (SrcBits == 64 && DestBits == 32);
19179 return (SrcBits == 64 && DestBits == 32);
19215 return Subtarget->hasFullFP16();
19222 if (!Subtarget->hasMVEIntegerOps())
19241 if (Ld->isExpandingLoad())
19245 if (Subtarget->hasMVEIntegerOps())
19258 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19290bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19292 if (Subtarget->useSoftFloat())
19301 return Subtarget->hasMVEFloatOps();
19319 unsigned Scale = 1;
19336 if ((V & (Scale - 1)) != 0)
19345 if (VT.
isVector() && Subtarget->hasNEON())
19348 !Subtarget->hasMVEFloatOps())
19351 bool IsNeg =
false;
19357 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19360 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19376 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19382 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19412 default:
return false;
19431 int Scale = AM.
Scale;
19436 default:
return false;
19444 Scale = Scale & ~1;
19445 return Scale == 2 || Scale == 4 || Scale == 8;
19462 if (Scale & 1)
return false;
19469 const int Scale = AM.
Scale;
19479 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19495 switch (AM.
Scale) {
19506 if (Subtarget->isThumb1Only())
19509 if (Subtarget->isThumb2())
19512 int Scale = AM.
Scale;
19514 default:
return false;
19518 if (Scale < 0) Scale = -Scale;
19526 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19539 if (Scale & 1)
return false;
19552 if (!Subtarget->isThumb())
19555 if (Subtarget->isThumb2())
19559 return Imm >= 0 && Imm <= 255;
19569 if (!Subtarget->isThumb())
19571 if (Subtarget->isThumb2())
19574 return AbsImm <= 255;
19609 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19613 int RHSC = (int)
RHS->getZExtValue();
19614 if (RHSC < 0 && RHSC > -256) {
19624 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19627 int RHSC = (int)
RHS->getZExtValue();
19628 if (RHSC < 0 && RHSC > -0x1000) {
19670 int RHSC = (int)
RHS->getZExtValue();
19671 if (RHSC < 0 && RHSC > -0x100) {
19676 }
else if (RHSC > 0 && RHSC < 0x100) {
19687 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19698 bool CanChangeType = isLE && !IsMasked;
19701 int RHSC = (int)
RHS->getZExtValue();
19703 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19704 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19709 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19720 if (VT == MVT::v4i16) {
19721 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19723 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19724 if (IsInRange(RHSC, 0x80, 1))
19726 }
else if (Alignment >= 4 &&
19727 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19728 IsInRange(RHSC, 0x80, 4))
19730 else if (Alignment >= 2 &&
19731 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19732 IsInRange(RHSC, 0x80, 2))
19734 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19747 if (Subtarget->isThumb1Only())
19754 bool isSEXTLoad =
false;
19755 bool IsMasked =
false;
19757 Ptr = LD->getBasePtr();
19758 VT = LD->getMemoryVT();
19759 Alignment = LD->getAlign();
19760 AS = LD->getAddressSpace();
19763 Ptr = ST->getBasePtr();
19764 VT = ST->getMemoryVT();
19765 Alignment = ST->getAlign();
19766 AS = ST->getAddressSpace();
19768 Ptr = LD->getBasePtr();
19769 VT = LD->getMemoryVT();
19770 Alignment = LD->getAlign();
19771 AS = LD->getAddressSpace();
19775 Ptr = ST->getBasePtr();
19776 VT = ST->getMemoryVT();
19777 Alignment = ST->getAlign();
19778 AS = ST->getAddressSpace();
19793 bool isLegal =
false;
19795 isLegal = Subtarget->hasMVEIntegerOps() &&
19797 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19798 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19800 if (Subtarget->isThumb2())
19825 bool isSEXTLoad =
false, isNonExt;
19826 bool IsMasked =
false;
19828 VT = LD->getMemoryVT();
19829 Ptr = LD->getBasePtr();
19830 Alignment = LD->getAlign();
19834 VT = ST->getMemoryVT();
19835 Ptr = ST->getBasePtr();
19836 Alignment = ST->getAlign();
19837 isNonExt = !ST->isTruncatingStore();
19839 VT = LD->getMemoryVT();
19840 Ptr = LD->getBasePtr();
19841 Alignment = LD->getAlign();
19846 VT = ST->getMemoryVT();
19847 Ptr = ST->getBasePtr();
19848 Alignment = ST->getAlign();
19849 isNonExt = !ST->isTruncatingStore();
19854 if (Subtarget->isThumb1Only()) {
19857 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19858 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19861 if (!RHS || RHS->getZExtValue() != 4)
19863 if (Alignment <
Align(4))
19867 Base =
Op->getOperand(0);
19873 bool isLegal =
false;
19875 isLegal = Subtarget->hasMVEIntegerOps() &&
19880 if (Subtarget->isThumb2())
19894 !Subtarget->isThumb2())
19908 const APInt &DemandedElts,
19910 unsigned Depth)
const {
19913 switch (
Op.getOpcode()) {
19920 if (
Op.getResNo() == 0) {
19931 case ARMISD::CMOV: {
19946 case Intrinsic::arm_ldaex:
19947 case Intrinsic::arm_ldrex: {
19955 case ARMISD::BFI: {
19962 const APInt &Mask =
Op.getConstantOperandAPInt(2);
19963 Known.
Zero &= Mask;
19967 case ARMISD::VGETLANEs:
19968 case ARMISD::VGETLANEu: {
19969 const SDValue &SrcSV =
Op.getOperand(0);
19975 "VGETLANE index out of bounds");
19980 EVT VT =
Op.getValueType();
19986 if (
Op.getOpcode() == ARMISD::VGETLANEs)
19987 Known = Known.
sext(DstSz);
19989 Known = Known.
zext(DstSz);
19994 case ARMISD::VMOVrh: {
19997 Known = KnownOp.
zext(32);
20000 case ARMISD::CSINC:
20001 case ARMISD::CSINV:
20002 case ARMISD::CSNEG: {
20010 if (
Op.getOpcode() == ARMISD::CSINC)
20013 else if (
Op.getOpcode() == ARMISD::CSINV)
20015 else if (
Op.getOpcode() == ARMISD::CSNEG)
20022 case ARMISD::VORRIMM:
20023 case ARMISD::VBICIMM: {
20024 unsigned Encoded =
Op.getConstantOperandVal(1);
20025 unsigned DecEltBits = 0;
20028 unsigned EltBits =
Op.getScalarValueSizeInBits();
20029 if (EltBits != DecEltBits) {
20038 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20039 APInt Imm(DecEltBits, DecodedVal);
20041 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20042 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20060 EVT VT =
Op.getValueType();
20066 assert(VT == MVT::i32 &&
"Unexpected integer type");
20073 unsigned Mask =
C->getZExtValue();
20076 unsigned ShrunkMask = Mask & Demanded;
20077 unsigned ExpandedMask = Mask | ~Demanded;
20081 if (ShrunkMask == 0)
20087 if (ExpandedMask == ~0U)
20090 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20091 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20093 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20094 if (NewMask == Mask)
20103 if (IsLegalMask(0xFF))
20104 return UseMask(0xFF);
20107 if (IsLegalMask(0xFFFF))
20108 return UseMask(0xFFFF);
20112 if (ShrunkMask < 256)
20113 return UseMask(ShrunkMask);
20117 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20118 return UseMask(ExpandedMask);
20133 unsigned Depth)
const {
20134 unsigned Opc =
Op.getOpcode();
20138 case ARMISD::LSRL: {
20142 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20144 unsigned ShAmt =
Op->getConstantOperandVal(2);
20154 case ARMISD::VBICIMM: {
20156 unsigned ModImm =
Op.getConstantOperandVal(1);
20157 unsigned EltBits = 0;
20159 if ((OriginalDemandedBits & Mask) == 0)
20165 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20180 if (!Subtarget->hasVFP2Base())
20184 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20196 unsigned S = Constraint.
size();
20198 switch (Constraint[0]) {
20210 }
else if (S == 2) {
20211 switch (Constraint[0]) {
20228 Value *CallOperandVal =
info.CallOperandVal;
20231 if (!CallOperandVal)
20235 switch (*constraint) {
20241 if (Subtarget->isThumb())
20256 if (PR == 0 || VT == MVT::Other)
20258 if (ARM::SPRRegClass.
contains(PR))
20259 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20260 if (ARM::DPRRegClass.
contains(PR))
20265using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20269 switch (Constraint.
size()) {
20272 switch (Constraint[0]) {
20274 if (Subtarget->isThumb())
20275 return RCPair(0U, &ARM::tGPRRegClass);
20276 return RCPair(0U, &ARM::GPRRegClass);
20278 if (Subtarget->isThumb())
20279 return RCPair(0U, &ARM::hGPRRegClass);
20282 if (Subtarget->isThumb1Only())
20283 return RCPair(0U, &ARM::tGPRRegClass);
20284 return RCPair(0U, &ARM::GPRRegClass);
20286 if (VT == MVT::Other)
20288 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20289 return RCPair(0U, &ARM::SPRRegClass);
20291 return RCPair(0U, &ARM::DPRRegClass);
20293 return RCPair(0U, &ARM::QPRRegClass);
20296 if (VT == MVT::Other)
20298 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20299 return RCPair(0U, &ARM::SPR_8RegClass);
20301 return RCPair(0U, &ARM::DPR_8RegClass);
20303 return RCPair(0U, &ARM::QPR_8RegClass);
20306 if (VT == MVT::Other)
20308 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20309 return RCPair(0U, &ARM::SPRRegClass);
20311 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20313 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20319 if (Constraint[0] ==
'T') {
20320 switch (Constraint[1]) {
20324 return RCPair(0U, &ARM::tGPREvenRegClass);
20326 return RCPair(0U, &ARM::tGPROddRegClass);
20335 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20336 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20339 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20340 return std::make_pair(
unsigned(ARM::LR),
getRegClassFor(MVT::i32));
20344 return {0,
nullptr};
20352 std::vector<SDValue> &
Ops,
20357 if (Constraint.
size() != 1)
20360 char ConstraintLetter = Constraint[0];
20361 switch (ConstraintLetter) {
20364 case 'I':
case 'J':
case 'K':
case 'L':
20365 case 'M':
case 'N':
case 'O':
20370 int64_t CVal64 =
C->getSExtValue();
20371 int CVal = (int) CVal64;
20374 if (CVal != CVal64)
20377 switch (ConstraintLetter) {
20381 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20382 if (CVal >= 0 && CVal <= 65535)
20386 if (Subtarget->isThumb1Only()) {
20389 if (CVal >= 0 && CVal <= 255)
20391 }
else if (Subtarget->isThumb2()) {
20405 if (Subtarget->isThumb1Only()) {
20410 if (CVal >= -255 && CVal <= -1)
20416 if (CVal >= -4095 && CVal <= 4095)
20422 if (Subtarget->isThumb1Only()) {
20429 }
else if (Subtarget->isThumb2()) {
20449 if (Subtarget->isThumb1Only()) {
20452 if (CVal >= -7 && CVal < 7)
20454 }
else if (Subtarget->isThumb2()) {
20474 if (Subtarget->isThumb1Only()) {
20477 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20483 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20489 if (Subtarget->isThumb1Only()) {
20491 if (CVal >= 0 && CVal <= 31)
20497 if (Subtarget->isThumb1Only()) {
20500 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20509 if (Result.getNode()) {
20510 Ops.push_back(Result);
20520 "Unhandled Opcode in getDivRemLibcall");
20526 case MVT::i8: LC = isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20527 case MVT::i16: LC = isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20528 case MVT::i32: LC = isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20529 case MVT::i64: LC = isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20538 "Unhandled Opcode in getDivRemArgList");
20542 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20543 EVT ArgVT =
N->getOperand(i).getValueType();
20546 Entry.IsSExt = isSigned;
20547 Entry.IsZExt = !isSigned;
20548 Args.push_back(Entry);
20556 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20557 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20558 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20559 "Register-based DivRem lowering only");
20560 unsigned Opcode =
Op->getOpcode();
20562 "Invalid opcode for Div/Rem lowering");
20564 EVT VT =
Op->getValueType(0);
20586 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20587 : Subtarget->hasDivideInARMMode();
20588 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20589 Op->getSimpleValueType(0) == MVT::i32) {
20591 const SDValue Dividend =
Op->getOperand(0);
20592 const SDValue Divisor =
Op->getOperand(1);
20593 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20597 SDValue Values[2] = {Div, Rem};
20616 if (
getTM().getTargetTriple().isOSWindows())
20619 TargetLowering::CallLoweringInfo CLI(DAG);
20623 Callee, std::move(Args))
20628 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20629 return CallInfo.first;
20635 EVT VT =
N->getValueType(0);
20641 Result[0], Result[1]);
20645 std::vector<Type*> RetTyParams;
20646 Type *RetTyElement;
20656 RetTyParams.push_back(RetTyElement);
20657 RetTyParams.push_back(RetTyElement);
20667 bool isSigned =
N->getOpcode() ==
ISD::SREM;
20672 if (
getTM().getTargetTriple().isOSWindows())
20679 Callee, std::move(Args))
20683 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20686 SDNode *ResNode = CallResult.first.getNode();
20693 assert(
getTM().getTargetTriple().isOSWindows() &&
20694 "unsupported target platform");
20702 "no-stack-arg-probe")) {
20706 Chain =
SP.getValue(1);
20723 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20724 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
20734 bool IsStrict =
Op->isStrictFPOpcode();
20735 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20736 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20738 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20739 "Unexpected type for custom-lowering FP_EXTEND");
20741 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20742 "With both FP DP and 16, any FP conversion is legal!");
20744 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20745 "With FP16, 16 to 32 conversion is legal!");
20748 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20753 Loc,
Op.getValueType(), SrcVal);
20768 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20769 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20770 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20771 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20775 {DstVT, MVT::Other}, {Chain, SrcVal});
20782 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20783 "Unexpected type for custom-lowering FP_EXTEND");
20784 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20789 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20793 bool IsStrict =
Op->isStrictFPOpcode();
20795 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20797 EVT DstVT =
Op.getValueType();
20798 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20801 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20802 "Unexpected type for custom-lowering FP_ROUND");
20804 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20805 "With both FP DP and 16, any FP conversion is legal!");
20810 if (SrcSz == 32 && Subtarget->hasFP16())
20815 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20816 "Unexpected type for custom-lowering FP_ROUND");
20820 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20832 if (v == 0xffffffff)
20844 bool ForCodeSize)
const {
20845 if (!Subtarget->hasVFP3Base())
20847 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20849 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20852 if (VT == MVT::f32)
20854 if (VT == MVT::f64 && Subtarget->hasFP64())
20867 case Intrinsic::arm_neon_vld1:
20868 case Intrinsic::arm_neon_vld2:
20869 case Intrinsic::arm_neon_vld3:
20870 case Intrinsic::arm_neon_vld4:
20871 case Intrinsic::arm_neon_vld2lane:
20872 case Intrinsic::arm_neon_vld3lane:
20873 case Intrinsic::arm_neon_vld4lane:
20874 case Intrinsic::arm_neon_vld2dup:
20875 case Intrinsic::arm_neon_vld3dup:
20876 case Intrinsic::arm_neon_vld4dup: {
20879 auto &
DL =
I.getDataLayout();
20880 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20882 Info.ptrVal =
I.getArgOperand(0);
20884 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20891 case Intrinsic::arm_neon_vld1x2:
20892 case Intrinsic::arm_neon_vld1x3:
20893 case Intrinsic::arm_neon_vld1x4: {
20896 auto &
DL =
I.getDataLayout();
20897 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20899 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20901 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20907 case Intrinsic::arm_neon_vst1:
20908 case Intrinsic::arm_neon_vst2:
20909 case Intrinsic::arm_neon_vst3:
20910 case Intrinsic::arm_neon_vst4:
20911 case Intrinsic::arm_neon_vst2lane:
20912 case Intrinsic::arm_neon_vst3lane:
20913 case Intrinsic::arm_neon_vst4lane: {
20916 auto &
DL =
I.getDataLayout();
20917 unsigned NumElts = 0;
20918 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20919 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20922 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20925 Info.ptrVal =
I.getArgOperand(0);
20927 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20934 case Intrinsic::arm_neon_vst1x2:
20935 case Intrinsic::arm_neon_vst1x3:
20936 case Intrinsic::arm_neon_vst1x4: {
20939 auto &
DL =
I.getDataLayout();
20940 unsigned NumElts = 0;
20941 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20942 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20945 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20948 Info.ptrVal =
I.getArgOperand(0);
20950 Info.align =
I.getParamAlign(0).valueOrOne();
20956 case Intrinsic::arm_mve_vld2q:
20957 case Intrinsic::arm_mve_vld4q: {
20961 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
20963 Info.ptrVal =
I.getArgOperand(0);
20971 case Intrinsic::arm_mve_vst2q:
20972 case Intrinsic::arm_mve_vst4q: {
20975 Type *VecTy =
I.getArgOperand(1)->getType();
20976 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
20978 Info.ptrVal =
I.getArgOperand(0);
20986 case Intrinsic::arm_mve_vldr_gather_base:
20987 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
20989 Info.ptrVal =
nullptr;
20991 Info.align =
Align(1);
20996 case Intrinsic::arm_mve_vldr_gather_base_wb:
20997 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
20999 Info.ptrVal =
nullptr;
21000 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21001 Info.align =
Align(1);
21006 case Intrinsic::arm_mve_vldr_gather_offset:
21007 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21009 Info.ptrVal =
nullptr;
21014 Info.align =
Align(1);
21019 case Intrinsic::arm_mve_vstr_scatter_base:
21020 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21022 Info.ptrVal =
nullptr;
21023 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21024 Info.align =
Align(1);
21029 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21030 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21032 Info.ptrVal =
nullptr;
21033 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21034 Info.align =
Align(1);
21039 case Intrinsic::arm_mve_vstr_scatter_offset:
21040 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21042 Info.ptrVal =
nullptr;
21047 Info.align =
Align(1);
21052 case Intrinsic::arm_ldaex:
21053 case Intrinsic::arm_ldrex: {
21054 auto &
DL =
I.getDataLayout();
21055 Type *ValTy =
I.getParamElementType(0);
21058 Info.ptrVal =
I.getArgOperand(0);
21060 Info.align =
DL.getABITypeAlign(ValTy);
21065 case Intrinsic::arm_stlex:
21066 case Intrinsic::arm_strex: {
21067 auto &
DL =
I.getDataLayout();
21068 Type *ValTy =
I.getParamElementType(1);
21071 Info.ptrVal =
I.getArgOperand(1);
21073 Info.align =
DL.getABITypeAlign(ValTy);
21078 case Intrinsic::arm_stlexd:
21079 case Intrinsic::arm_strexd:
21081 Info.memVT = MVT::i64;
21082 Info.ptrVal =
I.getArgOperand(2);
21084 Info.align =
Align(8);
21089 case Intrinsic::arm_ldaexd:
21090 case Intrinsic::arm_ldrexd:
21092 Info.memVT = MVT::i64;
21093 Info.ptrVal =
I.getArgOperand(0);
21095 Info.align =
Align(8);
21109 assert(Ty->isIntegerTy());
21111 unsigned Bits = Ty->getPrimitiveSizeInBits();
21112 if (Bits == 0 || Bits > 32)
21118 unsigned Index)
const {
21128 if (!Subtarget->hasDataBarrier()) {
21132 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21133 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21134 Builder.getInt32(0), Builder.getInt32(7),
21135 Builder.getInt32(10), Builder.getInt32(5)};
21136 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
21146 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
21167 if (Subtarget->preferISHSTBarriers())
21200 bool has64BitAtomicStore;
21201 if (Subtarget->isMClass())
21202 has64BitAtomicStore =
false;
21203 else if (Subtarget->isThumb())
21204 has64BitAtomicStore = Subtarget->hasV7Ops();
21206 has64BitAtomicStore = Subtarget->hasV6Ops();
21208 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21222 bool has64BitAtomicLoad;
21223 if (Subtarget->isMClass())
21224 has64BitAtomicLoad =
false;
21225 else if (Subtarget->isThumb())
21226 has64BitAtomicLoad = Subtarget->hasV7Ops();
21228 has64BitAtomicLoad = Subtarget->hasV6Ops();
21244 if (Subtarget->isMClass())
21245 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21246 else if (Subtarget->isThumb())
21247 hasAtomicRMW = Subtarget->hasV7Ops();
21249 hasAtomicRMW = Subtarget->hasV6Ops();
21250 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21274 bool HasAtomicCmpXchg;
21275 if (Subtarget->isMClass())
21276 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21277 else if (Subtarget->isThumb())
21278 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21280 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21282 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21289 return InsertFencesForAtomic;
21294 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21300 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21301 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21303 RTLIB::LibcallImpl SecurityCookieVar =
21304 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21305 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21306 SecurityCookieVar != RTLIB::Unsupported) {
21317 F->addParamAttr(0, Attribute::AttrKind::InReg);
21324 unsigned &
Cost)
const {
21326 if (!Subtarget->hasNEON())
21355 unsigned Opcode =
Op.getOpcode();
21357 case ARMISD::VORRIMM:
21358 case ARMISD::VBICIMM:
21366 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21370 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21375 if (!Subtarget->hasV7Ops())
21381 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21383 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21391 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21400 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21406 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21408 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21411 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21413 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21414 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21415 if (!Subtarget->isLittle())
21417 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21418 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21419 return Builder.CreateOr(
21420 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21424 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21425 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21428 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21429 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21434 if (!Subtarget->hasV7Ops())
21436 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21442 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21450 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21454 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21455 if (!Subtarget->isLittle())
21457 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21460 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21464 CallInst *CI = Builder.CreateCall(
21465 Strex, {Builder.CreateZExtOrBitCast(
21475 return Subtarget->isMClass();
21483 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21490 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21493 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21501 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21509 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21512 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21517 if (Subtarget->hasNEON() && VecSize == 64)
21519 return VecSize % 128 == 0;
21523 if (Subtarget->hasNEON())
21525 if (Subtarget->hasMVEIntegerOps())
21545 "Invalid interleave factor");
21546 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21548 "Unmatched number of shufflevectors and indices");
21553 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21556 Type *EltTy = VecTy->getElementType();
21559 Align Alignment = LI->getAlign();
21577 Value *BaseAddr = LI->getPointerOperand();
21579 if (NumLoads > 1) {
21583 VecTy->getNumElements() / NumLoads);
21589 if (Subtarget->hasNEON()) {
21590 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21591 Type *Tys[] = {VecTy, PtrTy};
21592 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21593 Intrinsic::arm_neon_vld3,
21594 Intrinsic::arm_neon_vld4};
21597 Ops.push_back(BaseAddr);
21598 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21600 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21603 assert((Factor == 2 || Factor == 4) &&
21604 "expected interleave factor of 2 or 4 for MVE");
21606 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21607 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21608 Type *Tys[] = {VecTy, PtrTy};
21611 Ops.push_back(BaseAddr);
21612 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21622 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21626 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21627 VecTy->getNumElements() * Factor);
21633 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21635 unsigned Index = Indices[i];
21637 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21641 SubVec = Builder.CreateIntToPtr(
21645 SubVecs[SV].push_back(SubVec);
21654 auto &SubVec = SubVecs[SVI];
21657 SVI->replaceAllUsesWith(WideVec);
21693 const APInt &GapMask)
const {
21695 "Invalid interleave factor");
21700 "Unexpected mask on store");
21703 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21705 unsigned LaneLen = VecTy->getNumElements() / Factor;
21706 Type *EltTy = VecTy->getElementType();
21710 Align Alignment =
SI->getAlign();
21727 Type *IntTy =
DL.getIntPtrType(EltTy);
21732 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21733 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21739 Value *BaseAddr =
SI->getPointerOperand();
21741 if (NumStores > 1) {
21744 LaneLen /= NumStores;
21754 if (Subtarget->hasNEON()) {
21755 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21756 Intrinsic::arm_neon_vst3,
21757 Intrinsic::arm_neon_vst4};
21758 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21759 Type *Tys[] = {PtrTy, SubVecTy};
21762 Ops.push_back(BaseAddr);
21764 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21765 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21767 assert((Factor == 2 || Factor == 4) &&
21768 "expected interleave factor of 2 or 4 for MVE");
21770 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21771 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21772 Type *Tys[] = {PtrTy, SubVecTy};
21775 Ops.push_back(BaseAddr);
21777 for (
unsigned F = 0;
F < Factor;
F++) {
21778 Ops.push_back(Builder.getInt32(
F));
21779 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21785 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21788 if (StoreCount > 0)
21789 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21790 BaseAddr, LaneLen * Factor);
21795 for (
unsigned i = 0; i < Factor; i++) {
21796 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21797 if (Mask[IdxI] >= 0) {
21798 Shuffles.
push_back(Builder.CreateShuffleVector(
21801 unsigned StartMask = 0;
21802 for (
unsigned j = 1; j < LaneLen; j++) {
21803 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21804 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21805 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21815 Shuffles.
push_back(Builder.CreateShuffleVector(
21836 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21840 Members += SubMembers;
21846 Members += SubMembers * AT->getNumElements();
21847 }
else if (Ty->isFloatTy()) {
21852 }
else if (Ty->isDoubleTy()) {
21864 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21866 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21868 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21881 return (Members > 0 && Members <= 4);
21887 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21889 return ABITypeAlign;
21894 assert(StackAlign &&
"data layout string is missing stack alignment");
21895 return std::min(ABITypeAlign, *StackAlign);
21904 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21913 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
21914 return IsHA || IsIntArray;
21918 const Constant *PersonalityFn)
const {
21926 const Constant *PersonalityFn)
const {
21939void ARMTargetLowering::insertCopiesSplitCSR(
21943 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21953 RC = &ARM::GPRRegClass;
21954 else if (ARM::DPRRegClass.
contains(*
I))
21955 RC = &ARM::DPRRegClass;
21965 assert(Entry->getParent()->getFunction().hasFnAttribute(
21966 Attribute::NoUnwind) &&
21967 "Function should be nounwind in insertCopiesSplitCSR!");
21968 Entry->addLiveIn(*
I);
21973 for (
auto *Exit : Exits)
21975 TII->get(TargetOpcode::COPY), *
I)
21986 return Subtarget->hasMVEIntegerOps();
21996 unsigned NumElements = VTy->getNumElements();
22003 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22004 return Subtarget->hasMVEFloatOps();
22009 return Subtarget->hasMVEIntegerOps() &&
22010 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22011 ScalarTy->isIntegerTy(32));
22015 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22026 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22028 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22030 if (TyWidth > 128) {
22031 int Stride = Ty->getNumElements() / 2;
22035 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22037 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22038 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22039 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22040 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22041 Value *LowerSplitAcc =
nullptr;
22042 Value *UpperSplitAcc =
nullptr;
22045 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22046 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22050 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22052 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22054 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22055 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22062 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22065 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22067 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22068 {ConstRotation, InputB, InputA});
22073 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22076 ConstRotation = ConstantInt::get(IntTy, 0);
22078 ConstRotation = ConstantInt::get(IntTy, 1);
22080 if (!ConstRotation)
22083 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22084 {ConstHalving, ConstRotation, InputA, InputB});
unsigned const MachineRegisterInfo * MRI
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool isNegatedInteger(SDValue Op)
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue LowerUADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue ConvertBooleanCarryToCarryFlag(SDValue BoolCarry, SelectionDAG &DAG)
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue ConvertCarryFlagToBooleanCarry(SDValue Flags, EVT VT, SelectionDAG &DAG)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static unsigned SelectPairHalf(unsigned Elements, ArrayRef< int > Mask, unsigned Index)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue 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.
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static constexpr int Concat[]
static bool isIntrinsic(const CallBase &Call, Intrinsic::ID ID)
static constexpr roundingMode rmTowardZero
LLVM_ABI bool getExactInverse(APFloat *Inv) const
If this value is normal and has an exact, normal, multiplicative inverse, store it in inv and return ...
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
unsigned logBase2() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
const ARMBaseRegisterInfo & getRegisterInfo() const
const uint32_t * getSjLjDispatchPreservedMask(const MachineFunction &MF) const
const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override
Code Generation virtual methods...
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const uint32_t * getTLSCallPreservedMask(const MachineFunction &MF) const
const uint32_t * getThisReturnPreservedMask(const MachineFunction &MF, CallingConv::ID) const
getThisReturnPreservedMask - Returns a call preserved mask specific to the case that 'returned' is on...
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
int getVarArgsFrameIndex() const
int getPromotedConstpoolIncrease() const
SmallPtrSet< const GlobalVariable *, 2 > & getGlobalsPromotedToConstantPool()
void setArgumentStackToRestore(unsigned v)
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
void setPromotedConstpoolIncrease(int Sz)
bool isThumb1OnlyFunction() const
void setArgRegsSaveSize(unsigned s)
bool isCmseNSEntryFunction() const
void setReturnRegsCount(unsigned s)
void setVarArgsFrameIndex(int Index)
unsigned getArgRegsSaveSize() const
void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV)
Indicate to the backend that GV has had its storage changed to inside a constant pool.
void setIsSplitCSR(bool s)
void setArgumentStackSize(unsigned size)
unsigned getArgumentStackSize() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
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.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
bool useLoadStackGuardNode(const Module &M) const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
bool lowerInterleavedLoad(Instruction *Load, Value *Mask, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor, const APInt &GapMask) const override
Lower an interleaved load into a vldN intrinsic.
std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override
Return the largest legal super-reg register class of the register class for the specified type and it...
bool preferSelectsOverBooleanArithmetic(EVT VT) const override
Should we prefer selects to doing arithmetic on boolean types.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
ARMTargetLowering(const TargetMachine &TM, const ARMSubtarget &STI)
bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const override
Does this target support complex deinterleaving with the given operation and type.
bool supportKCFIBundles() const override
Return true if the target supports kcfi operand bundles.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
Type * shouldConvertSplatType(ShuffleVectorInst *SVI) const override
Given a shuffle vector SVI representing a vector splat, return a new scalar type of size equal to SVI...
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
Instruction * makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
const char * LowerXConstraint(EVT ConstraintVT) const override
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool isVarArg) const
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
allowsMisalignedMemoryAccesses - Returns true if the target allows unaligned memory accesses of the s...
bool isLegalInterleavedAccessType(unsigned Factor, FixedVectorType *VecTy, Align Alignment, const DataLayout &DL) const
Returns true if VecTy is a legal interleaved access type.
bool isVectorLoadExtDesirable(SDValue ExtVal) const override
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, unsigned &Cost) const override
Return true if the target can combine store(extractelement VectorTy,Idx).
bool useSoftFloat() const override
bool alignLoopsWithOptSize() const override
Should loops be aligned even when the function is marked OptSize (but not MinSize).
SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const
bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override
Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail ...
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
bool functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const override
Returns true if an argument of type Ty needs to be passed in a contiguous block of registers in calli...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
const ARMBaseTargetMachine & getTM() const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
ShiftLegalizationStrategy preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, unsigned ExpansionFactor) const override
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPostIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mo...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
bool isFloatingPointOperation() const
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
The address of a basic block.
static BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
LLVM_ABI int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, uint32_t BitWidth) const
If this is a constant FP splat and the splatted constant FP is an exact power or 2,...
CCState - This class holds information needed while lowering arguments and return values.
void getInRegsParamInfo(unsigned InRegsParamRecordIndex, unsigned &BeginReg, unsigned &EndReg) const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
void rewindByValRegsInfo()
unsigned getInRegsParamsProcessed() const
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void addInRegsParamInfo(unsigned RegBegin, unsigned RegEnd)
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
unsigned getInRegsParamsCount() const
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
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...
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
StringRef getPrivateGlobalPrefix() const
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool 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.
LLVM_ABI CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const
Get the CallingConv that should be used for the specified libcall.
LLVM_ABI 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)
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getFunctionContextIndex() const
Return the index for the function context object.
Properties which a MachineFunction may have at a given point in time.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & 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,...
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.
StringRef - Represent a constant reference to a string, i.e.
const unsigned char * bytes_end() const
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - 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 a n/2-bit urem by constant and other arit...
bool isPositionIndependent() const
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual ArrayRef< MCPhysReg > getRoundingControlRegisters() const
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
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.
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ 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,...
@ 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...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ 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)
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
FunctionAddr VTableAddr uintptr_t uintptr_t Data
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
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.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)