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()) {
965 if (Subtarget->hasDSP()) {
975 if (Subtarget->hasBaseDSP()) {
983 if (Subtarget->isThumb1Only()) {
987 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
988 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1003 if (Subtarget->hasMVEIntegerOps())
1007 if (Subtarget->isThumb1Only()) {
1013 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1027 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1036 if (Subtarget->hasPerfMon())
1040 if (!Subtarget->hasV6Ops())
1043 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1044 : Subtarget->hasDivideInARMMode();
1051 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1063 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1064 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1067 HasStandaloneRem =
false;
1094 if (TT.isOSWindows())
1101 InsertFencesForAtomic =
false;
1102 if (Subtarget->hasAnyDataBarrier() &&
1103 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1107 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1112 if (!Subtarget->hasAcquireRelease() ||
1115 InsertFencesForAtomic =
true;
1121 if (Subtarget->hasDataBarrier())
1122 InsertFencesForAtomic =
true;
1142 if (!InsertFencesForAtomic) {
1149 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1161 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1162 Subtarget->hasForced32BitAtomics()) {
1176 if (!Subtarget->hasV6Ops()) {
1182 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1183 !Subtarget->isThumb1Only()) {
1212 if (Subtarget->hasFullFP16()) {
1222 if (Subtarget->hasFullFP16())
1237 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1238 !Subtarget->isThumb1Only()) {
1245 if (!Subtarget->hasVFP4Base()) {
1251 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1253 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1261 if (!Subtarget->hasFP16()) {
1281 if (Subtarget->hasFPARMv8Base()) {
1291 if (Subtarget->hasFP64())
1295 if (Subtarget->hasNEON()) {
1305 if (Subtarget->hasFullFP16()) {
1342 if (Subtarget->hasNEON()) {
1354 if (Subtarget->hasV8Ops()) {
1364 if (Subtarget->hasFullFP16()) {
1387 if (TT.isOSWindows()) {
1404 if (Subtarget->hasMVEIntegerOps())
1407 if (Subtarget->hasV6Ops())
1409 if (Subtarget->isThumb1Only())
1412 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1413 Subtarget->isThumb2()) {
1419 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1420 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1442 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1450 return Subtarget->useSoftFloat();
1454 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1467std::pair<const TargetRegisterClass *, uint8_t>
1478 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1479 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1480 RRC = &ARM::DPRRegClass;
1485 if (Subtarget->useNEONForSinglePrecisionFP())
1488 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1489 case MVT::v4f32:
case MVT::v2f64:
1490 RRC = &ARM::DPRRegClass;
1494 RRC = &ARM::DPRRegClass;
1498 RRC = &ARM::DPRRegClass;
1502 return std::make_pair(RRC,
Cost);
1511 if ((Subtarget->hasMVEIntegerOps() &&
1512 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1513 VT == MVT::v16i8)) ||
1514 (Subtarget->hasMVEFloatOps() &&
1515 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1529 if (Subtarget->hasNEON()) {
1530 if (VT == MVT::v4i64)
1531 return &ARM::QQPRRegClass;
1532 if (VT == MVT::v8i64)
1533 return &ARM::QQQQPRRegClass;
1535 if (Subtarget->hasMVEIntegerOps()) {
1536 if (VT == MVT::v4i64)
1537 return &ARM::MQQPRRegClass;
1538 if (VT == MVT::v8i64)
1539 return &ARM::MQQQQPRRegClass;
1548 Align &PrefAlign)
const {
1555 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1567 unsigned NumVals =
N->getNumValues();
1571 for (
unsigned i = 0; i != NumVals; ++i) {
1572 EVT VT =
N->getValueType(i);
1573 if (VT == MVT::Glue || VT == MVT::Other)
1579 if (!
N->isMachineOpcode())
1587 if (
MCID.getNumDefs() == 0)
1589 if (!Itins->isEmpty() &&
1590 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1604 return Const->getZExtValue() == 16;
1612 return Const->getZExtValue() == 16;
1620 return Const->getZExtValue() == 16;
1689 bool isVarArg)
const {
1708 if (!
getTM().isAAPCS_ABI())
1710 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1718 if (!
getTM().isAAPCS_ABI()) {
1719 if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() && !isVarArg)
1722 }
else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1731 bool isVarArg)
const {
1732 return CCAssignFnForNode(CC,
false, isVarArg);
1736 bool isVarArg)
const {
1737 return CCAssignFnForNode(CC,
true, isVarArg);
1744 bool isVarArg)
const {
1745 switch (getEffectiveCallingConv(CC, isVarArg)) {
1771 if (Subtarget->hasFullFP16()) {
1772 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1784 if (Subtarget->hasFullFP16()) {
1785 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1798SDValue ARMTargetLowering::LowerCallResult(
1802 SDValue ThisVal,
bool isCmseNSCall)
const {
1810 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1811 CCValAssign VA = RVLocs[i];
1815 if (i == 0 && isThisReturn) {
1817 "unexpected return calling convention register assignment");
1835 if (!Subtarget->isLittle())
1837 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1852 if (!Subtarget->isLittle())
1854 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1884 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1895std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1897 bool IsTailCall,
int SPDiff)
const {
1899 MachinePointerInfo DstInfo;
1919 return std::make_pair(DstAddr, DstInfo);
1928ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1941 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1944 int SrcFI = SrcFrameIdxNode->getIndex();
1945 int DstFI = DstFrameIdxNode->getIndex();
1947 "byval passed in non-fixed stack slot");
1969 if (SrcOffset == DstOffset)
1977 RegsToPassVector &RegsToPass,
1984 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1985 unsigned id = Subtarget->isLittle() ? 0 : 1;
1997 MachinePointerInfo DstInfo;
1998 std::tie(DstAddr, DstInfo) =
1999 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2016 SelectionDAG &DAG = CLI.
DAG;
2018 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2019 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2020 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2027 const CallBase *CB = CLI.
CB;
2030 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2032 MachineFunction::CallSiteInfo CSInfo;
2033 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2034 bool isThisReturn =
false;
2035 bool isCmseNSCall =
false;
2036 bool isSibCall =
false;
2037 bool PreferIndirect =
false;
2038 bool GuardWithBTI =
false;
2048 !Subtarget->noBTIAtReturnTwice())
2056 isCmseNSCall =
true;
2059 if (!Subtarget->supportsTailCall())
2075 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2076 count_if(GV->users(), [&BB](
const User *U) {
2077 return isa<Instruction>(U) &&
2078 cast<Instruction>(U)->getParent() == BB;
2085 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2099 "site marked musttail");
2102 unsigned NumBytes = CCInfo.getStackSize();
2111 if (isTailCall && !isSibCall) {
2112 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2113 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2118 assert(StackAlign &&
"data layout string is missing stack alignment");
2119 NumBytes =
alignTo(NumBytes, *StackAlign);
2124 SPDiff = NumReusableBytes - NumBytes;
2128 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2144 RegsToPassVector RegsToPass;
2153 DenseMap<unsigned, SDValue> ByValTemporaries;
2157 for (
const CCValAssign &VA : ArgLocs) {
2159 SDValue Src = OutVals[ArgIdx];
2160 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2162 if (!
Flags.isByVal())
2166 MachinePointerInfo DstInfo;
2167 std::tie(Dst, DstInfo) =
2168 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2169 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2171 if (Copy == NoCopy) {
2176 }
else if (Copy == CopyOnce) {
2180 ByValTemporaries[ArgIdx] = Src;
2182 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2186 int TempFrameIdx = MFI.CreateStackObject(
2187 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2195 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2196 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2198 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2199 ByValTemporaries[ArgIdx] = Temp;
2202 if (!ByValCopyChains.
empty())
2212 bool AfterFormalArgLoads =
false;
2216 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2218 ++i, ++realArgIdx) {
2219 CCValAssign &VA = ArgLocs[i];
2220 SDValue Arg = OutVals[realArgIdx];
2221 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2222 bool isByVal =
Flags.isByVal();
2242 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2244 if (ByValTempChain) {
2249 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2250 if (Outs[
I].
Flags.isByVal())
2258 FrameIndexSDNode *FIN =
2263 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2266 for (
const CCValAssign &VA : ArgLocs) {
2274 if (!IncomingLoad.
empty()) {
2282 AfterFormalArgLoads =
true;
2294 auto ArgVT = Outs[realArgIdx].ArgVT;
2295 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2313 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2314 StackPtr, MemOpChains, isTailCall, SPDiff);
2318 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2319 StackPtr, MemOpChains, isTailCall, SPDiff);
2323 MachinePointerInfo DstInfo;
2324 std::tie(DstAddr, DstInfo) =
2325 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2329 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2330 StackPtr, MemOpChains, isTailCall, SPDiff);
2332 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2333 Outs[0].VT == MVT::i32) {
2335 "unexpected calling convention register assignment");
2337 "unexpected use of 'returned'");
2338 isThisReturn =
true;
2343 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2344 }
else if (isByVal) {
2346 unsigned offset = 0;
2350 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2351 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2354 bool NeedsStackCopy;
2355 if (
auto It = ByValTemporaries.
find(realArgIdx);
2356 It != ByValTemporaries.
end()) {
2357 ByValSrc = It->second;
2358 NeedsStackCopy =
true;
2361 NeedsStackCopy = !isTailCall;
2365 if (CurByValIdx < ByValArgsCount) {
2366 unsigned RegBegin, RegEnd;
2367 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2371 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2375 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2378 RegsToPass.push_back(std::make_pair(j, Load));
2383 offset = RegEnd - RegBegin;
2385 CCInfo.nextInRegsParam();
2390 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2393 MachinePointerInfo DstInfo;
2394 std::tie(Dst, DstInfo) =
2395 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2403 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2404 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2411 MachinePointerInfo DstInfo;
2412 std::tie(DstAddr, DstInfo) =
2413 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2420 if (!MemOpChains.
empty())
2426 for (
const auto &[
Reg,
N] : RegsToPass) {
2434 bool isDirect =
false;
2437 const Triple &
TT = TM.getTargetTriple();
2438 const GlobalValue *GVal =
nullptr;
2440 GVal =
G->getGlobal();
2441 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2443 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2444 bool isLocalARMFunc =
false;
2447 if (Subtarget->genLongCalls()) {
2449 "long-calls codegen is not position independent!");
2454 if (Subtarget->genExecuteOnly()) {
2455 if (Subtarget->useMovt())
2467 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2473 const char *Sym = S->getSymbol();
2475 if (Subtarget->genExecuteOnly()) {
2476 if (Subtarget->useMovt())
2488 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2495 if (!PreferIndirect) {
2500 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2502 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2503 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2505 ARMISD::WrapperPIC, dl, PtrVt,
2512 }
else if (Subtarget->isTargetCOFF()) {
2513 assert(Subtarget->isTargetWindows() &&
2514 "Windows is the only supported COFF target");
2518 else if (!TM.shouldAssumeDSOLocal(GVal))
2525 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2534 const char *Sym = S->getSymbol();
2535 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2537 ARMConstantPoolValue *CPV =
2539 ARMPCLabelIndex, 4);
2541 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2546 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2553 assert(!isARMFunc && !isDirect &&
2554 "Cannot handle call to ARM function or direct call");
2558 "call to non-secure function would require "
2559 "passing arguments on stack",
2565 "call to non-secure function would return value through pointer",
2572 if (Subtarget->isThumb()) {
2574 CallOpc = ARMISD::t2CALL_BTI;
2575 else if (isCmseNSCall)
2576 CallOpc = ARMISD::tSECALL;
2577 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2578 CallOpc = ARMISD::CALL_NOLINK;
2580 CallOpc = ARMISD::CALL;
2582 if (!isDirect && !Subtarget->hasV5TOps())
2583 CallOpc = ARMISD::CALL_NOLINK;
2584 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2586 !Subtarget->hasMinSize())
2588 CallOpc = ARMISD::CALL_NOLINK;
2590 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2597 if (isTailCall && !isSibCall) {
2602 std::vector<SDValue>
Ops;
2603 Ops.push_back(Chain);
2604 Ops.push_back(Callee);
2612 for (
const auto &[
Reg,
N] : RegsToPass)
2616 const uint32_t *
Mask;
2617 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2625 isThisReturn =
false;
2631 assert(Mask &&
"Missing call preserved mask for calling convention");
2635 Ops.push_back(InGlue);
2648 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2659 uint64_t CalleePopBytes =
2662 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2668 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2669 InVals, isThisReturn,
2670 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2677void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2678 Align Alignment)
const {
2680 Alignment = std::max(Alignment,
Align(4));
2686 unsigned AlignInRegs = Alignment.
value() / 4;
2687 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2688 for (
unsigned i = 0; i < Waste; ++i)
2694 unsigned Excess = 4 * (ARM::R4 -
Reg);
2701 if (NSAAOffset != 0 &&
Size > Excess) {
2713 unsigned ByValRegBegin =
Reg;
2714 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2718 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2724 Size = std::max<int>(
Size - Excess, 0);
2732bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2738 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2739 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2740 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2741 const SelectionDAG &DAG = CLI.
DAG;
2746 assert(Subtarget->supportsTailCall());
2759 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2761 if (!(Subtarget->isThumb1Only() ||
2762 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2763 AddressRegisters.
insert(ARM::R12);
2764 for (
const CCValAssign &AL : ArgLocs)
2766 AddressRegisters.
erase(
AL.getLocReg());
2767 if (AddressRegisters.
empty()) {
2768 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2787 <<
" (guaranteed tail-call CC)\n");
2788 return CalleeCC == CallerCC;
2793 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2795 if (isCalleeStructRet != isCallerStructRet) {
2808 const GlobalValue *GV =
G->getGlobal();
2811 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2812 TT.isOSBinFormatMachO())) {
2821 getEffectiveCallingConv(CalleeCC, isVarArg),
2822 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
2829 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2830 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2831 if (CalleeCC != CallerCC) {
2832 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2833 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2842 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2850 const MachineRegisterInfo &MRI = MF.
getRegInfo();
2852 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2871 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2880 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2893 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2896 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2900 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2905 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2927 bool isLittleEndian = Subtarget->isLittle();
2930 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2939 "secure entry function would return value through pointer",
2944 for (
unsigned i = 0, realRVLocIdx = 0;
2946 ++i, ++realRVLocIdx) {
2947 CCValAssign &VA = RVLocs[i];
2950 SDValue Arg = OutVals[realRVLocIdx];
2951 bool ReturnF16 =
false;
2953 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
2986 auto RetVT = Outs[realRVLocIdx].ArgVT;
3008 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3012 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3018 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3030 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3032 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3037 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3047 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3073 !Subtarget->isMClass()) {
3074 if (Subtarget->isThumb1Only())
3081 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3084bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3085 if (
N->getNumValues() != 1)
3087 if (!
N->hasNUsesOfValue(1, 0))
3091 SDNode *
Copy = *
N->user_begin();
3095 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3097 TCChain =
Copy->getOperand(0);
3098 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3099 SDNode *VMov =
Copy;
3101 SmallPtrSet<SDNode*, 2>
Copies;
3102 for (SDNode *U : VMov->
users()) {
3110 for (SDNode *U : VMov->
users()) {
3111 SDValue UseChain =
U->getOperand(0);
3119 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3127 if (!
Copy->hasOneUse())
3134 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3136 TCChain =
Copy->getOperand(0);
3141 bool HasRet =
false;
3142 for (
const SDNode *U :
Copy->users()) {
3143 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3144 U->getOpcode() != ARMISD::INTRET_GLUE)
3156bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3157 if (!Subtarget->supportsTailCall())
3174 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3190 EVT PtrVT =
Op.getValueType();
3200 if (Subtarget->genExecuteOnly()) {
3205 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 &&
4464 if (
Op->getFlags().hasNoSignedWrap())
4480 (isIntEqualitySetCC(CC) ||
4489 const SDLoc &dl)
const {
4491 unsigned C = RHSC->getZExtValue();
4555 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4559 unsigned Mask =
LHS.getConstantOperandVal(1);
4561 uint64_t RHSV = RHSC->getZExtValue();
4562 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4564 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4578 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4581 LHS.getConstantOperandVal(1) < 31) {
4582 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4607 unsigned CompareType;
4610 CompareType = ARMISD::CMP;
4615 CompareType = ARMISD::CMPZ;
4624 if (CompareType != ARMISD::CMPZ &&
isCMN(
RHS, CC, DAG)) {
4625 CompareType = ARMISD::CMN;
4627 }
else if (CompareType != ARMISD::CMPZ &&
isCMN(
LHS, CC, DAG)) {
4628 CompareType = ARMISD::CMN;
4640 bool Signaling)
const {
4641 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4647 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4656std::pair<SDValue, SDValue>
4659 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4671 switch (
Op.getOpcode()) {
4723 return std::make_pair(
Value, OverflowCmp);
4736 return Cmp.getValue(1);
4764 return DAG.
getNode(ARMISD::CMOV,
DL, VT, Zero, One, ARMcc, Flags);
4776 EVT VT =
Op.getValueType();
4777 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4780 switch (
Op.getOpcode()) {
4794 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4800 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4803 ARMcc, OverflowCmp);
4813 EVT VT =
Op.getValueType();
4814 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4824 switch (
Op->getOpcode()) {
4826 NewOpcode = ARMISD::UQADD8b;
4829 NewOpcode = ARMISD::QADD8b;
4832 NewOpcode = ARMISD::UQSUB8b;
4835 NewOpcode = ARMISD::QSUB8b;
4840 switch (
Op->getOpcode()) {
4842 NewOpcode = ARMISD::UQADD16b;
4845 NewOpcode = ARMISD::QADD16b;
4848 NewOpcode = ARMISD::UQSUB16b;
4851 NewOpcode = ARMISD::QSUB16b;
4859 DAG.
getNode(NewOpcode, dl, MVT::i32,
4870 unsigned Opc =
Cond.getOpcode();
4872 if (
Cond.getResNo() == 1 &&
4880 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4881 EVT VT =
Op.getValueType();
4883 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4891 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4892 const ConstantSDNode *CMOVTrue =
4894 const ConstantSDNode *CMOVFalse =
4897 if (CMOVTrue && CMOVFalse) {
4903 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
4905 False = SelectFalse;
4906 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
4912 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
4913 Cond.getOperand(3), DAG);
4928 bool &swpCmpOps,
bool &swpVselOps) {
4956 swpCmpOps = !swpCmpOps;
4957 swpVselOps = !swpVselOps;
4980 if (!Subtarget->hasFP64() && VT == MVT::f64) {
4982 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
4984 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
4998 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
5019 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5021 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5042 EVT VT =
Op.getValueType();
5064 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5077 int64_t PosVal = std::max(Val1, Val2);
5078 int64_t NegVal = std::min(Val1, Val2);
5090 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5093 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5125 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5130 if (*K != KTmp || V != VTmp)
5141bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5143 return !Subtarget->hasVFP2Base();
5145 return !Subtarget->hasFP64();
5147 return !Subtarget->hasFullFP16();
5155 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5163 if (TVal == ~FVal) {
5164 Opcode = ARMISD::CSINV;
5165 }
else if (TVal == ~FVal + 1) {
5166 Opcode = ARMISD::CSNEG;
5167 }
else if (TVal + 1 == FVal) {
5168 Opcode = ARMISD::CSINC;
5169 }
else if (TVal == FVal + 1) {
5170 Opcode = ARMISD::CSINC;
5173 InvertCond = !InvertCond;
5180 if (Opcode != ARMISD::CSINC &&
5184 InvertCond = !InvertCond;
5190 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5193 InvertCond = !InvertCond;
5200 EVT VT =
Op.getValueType();
5204 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5216 if (VT == MVT::i32 &&
5235 if (
Op.getValueType().isInteger()) {
5243 LHS.getValueType() ==
RHS.getValueType()) {
5244 EVT VT =
LHS.getValueType();
5250 Shift = DAG.
getNOT(dl, Shift, VT);
5262 if (
LHS.getValueType() == MVT::i32) {
5266 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5272 EVT VT =
Op.getValueType();
5273 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5277 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5282 if (!
RHS.getNode()) {
5288 if (
LHS.getValueType() == MVT::i32) {
5299 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5300 TrueVal.getValueType() == MVT::f32 ||
5301 TrueVal.getValueType() == MVT::f64)) {
5315 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5325 if (Subtarget->hasFPARMv8Base() &&
5327 (
TrueVal.getValueType() == MVT::f16 ||
5328 TrueVal.getValueType() == MVT::f32 ||
5329 TrueVal.getValueType() == MVT::f64)) {
5330 bool swpCmpOps =
false;
5331 bool swpVselOps =
false;
5345 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5348 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5358 if (!
N->hasOneUse())
5361 if (!
N->getNumValues())
5363 EVT VT =
Op.getValueType();
5364 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5381 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5382 Ld->getPointerInfo(), Ld->getAlign(),
5383 Ld->getMemOperand()->getFlags());
5399 SDValue Ptr = Ld->getBasePtr();
5401 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5402 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5407 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5408 Ld->getPointerInfo().getWithOffset(4),
5410 Ld->getMemOperand()->getFlags());
5428 bool LHSSeenZero =
false;
5430 bool RHSSeenZero =
false;
5432 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5443 if (
LHS.getValueType() == MVT::f32) {
5449 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5461 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5462 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5477 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5496 unsigned Opc =
Cond.getOpcode();
5498 !Subtarget->isThumb1Only();
5499 if (
Cond.getResNo() == 1 &&
5509 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5514 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5529 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5534 if (!
RHS.getNode()) {
5542 unsigned Opc =
LHS.getOpcode();
5544 !Subtarget->isThumb1Only();
5556 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5563 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5567 if (
LHS.getValueType() == MVT::i32) {
5570 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5573 SDNodeFlags
Flags =
Op->getFlags();
5574 if (
Flags.hasNoNaNs() &&
5579 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5593 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5607 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5610 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5615 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5616 Addr,
Op.getOperand(2), JTI);
5620 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5624 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5627 DAG.
getLoad(PTy, dl, Chain, Addr,
5630 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5635 EVT VT =
Op.getValueType();
5638 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5639 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5647 const EVT OpTy =
Op.getOperand(0).getValueType();
5648 if (OpTy == MVT::v4f32)
5650 else if (OpTy == MVT::v4f16 && HasFullFP16)
5652 else if (OpTy == MVT::v8f16 && HasFullFP16)
5657 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5660 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5665 EVT VT =
Op.getValueType();
5669 bool IsStrict =
Op->isStrictFPOpcode();
5670 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5672 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5685 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5686 CallOptions, Loc, Chain);
5696 Loc,
Op.getValueType(), SrcVal);
5705 EVT VT =
Op.getValueType();
5707 EVT FromVT =
Op.getOperand(0).getValueType();
5709 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5711 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5712 Subtarget->hasFP64())
5714 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5715 Subtarget->hasFullFP16())
5717 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5718 Subtarget->hasMVEFloatOps())
5720 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5721 Subtarget->hasMVEFloatOps())
5724 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5741 EVT VT =
Op.getValueType();
5744 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5750 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5751 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5752 "Invalid type for custom lowering!");
5757 if (VT == MVT::v4f32)
5758 DestVecType = MVT::v4i32;
5759 else if (VT == MVT::v4f16 && HasFullFP16)
5760 DestVecType = MVT::v4i16;
5761 else if (VT == MVT::v8f16 && HasFullFP16)
5762 DestVecType = MVT::v8i16;
5768 switch (
Op.getOpcode()) {
5780 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5785 EVT VT =
Op.getValueType();
5788 if (isUnsupportedFloatingType(VT)) {
5798 CallOptions, SDLoc(
Op)).first;
5809 EVT VT =
Op.getValueType();
5813 bool UseNEON = !InGPR && Subtarget->hasNEON();
5820 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5827 if (SrcVT == MVT::f32) {
5830 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5833 }
else if (VT == MVT::f32)
5834 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5849 if (VT == MVT::f32) {
5861 if (SrcVT == MVT::f64)
5870 if (VT == MVT::f32) {
5883 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5891 EVT VT =
Op.getValueType();
5893 unsigned Depth =
Op.getConstantOperandVal(0);
5895 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5899 MachinePointerInfo());
5908 const ARMBaseRegisterInfo &ARI =
5909 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
5914 EVT VT =
Op.getValueType();
5916 unsigned Depth =
Op.getConstantOperandVal(0);
5921 MachinePointerInfo());
5929 return StringSwitch<Register>(
RegName)
5930 .Case(
"sp", ARM::SP)
5941 assert(
N->getValueType(0) == MVT::i64
5942 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
5945 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
5985 const APInt &APIntIndex = Index->getAPIntValue();
5987 NewIndex *= APIntIndex;
6016 EVT SrcVT =
Op.getValueType();
6017 EVT DstVT =
N->getValueType(0);
6019 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6020 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6021 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
6024 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6025 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6026 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6033 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6045 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6053 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6055 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6057 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6077 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6086 EVT VT =
Op.getValueType();
6108 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6118 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6129 EVT VT =
Op.getValueType();
6150 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6171 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6223 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6251 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6281 EVT VT =
N->getValueType(0);
6282 if (VT.
isVector() && ST->hasNEON()) {
6291 if (ElemTy == MVT::i8) {
6299 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6302 unsigned NumBits = ElemTy.getSizeInBits();
6304 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6314 if (ElemTy == MVT::i64) {
6327 if (!ST->hasV6T2Ops())
6336 EVT VT =
N->getValueType(0);
6339 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6340 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6341 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6342 "Unexpected type for custom ctpop lowering");
6350 unsigned EltSize = 8;
6373 Op =
Op.getOperand(0);
6375 APInt SplatBits, SplatUndef;
6376 unsigned SplatBitSize;
6379 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6381 SplatBitSize > ElementBits)
6392 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6396 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6407 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6412 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6413 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6422 EVT VT =
N->getValueType(0);
6437 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6439 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6444 "unexpected vector shift opcode");
6446 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6447 unsigned VShiftOpc =
6448 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6449 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6455 EVT ShiftVT =
N->getOperand(1).getValueType();
6458 unsigned VShiftOpc =
6459 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6460 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6465 EVT VT =
N->getValueType(0);
6474 "Unknown shift to lower!");
6476 unsigned ShOpc =
N->getOpcode();
6477 if (ST->hasMVEIntegerOps()) {
6479 unsigned ShPartsOpc = ARMISD::LSLL;
6500 ShPartsOpc = ARMISD::LSRL;
6502 ShPartsOpc = ARMISD::ASRL;
6507 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6521 if (ST->isThumb1Only())
6526 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6530 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6534 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6542 bool Invert =
false;
6549 EVT VT =
Op.getValueType();
6557 assert(ST->hasMVEIntegerOps() &&
6558 "No hardware support for integer vector comparison!");
6560 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6581 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6585 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6595 switch (SetCCOpcode) {
6599 if (ST->hasMVEFloatOps()) {
6602 Invert =
true; [[fallthrough]];
6607 case ISD::SETLT: Swap =
true; [[fallthrough]];
6611 case ISD::SETLE: Swap =
true; [[fallthrough]];
6627 Result = DAG.
getNOT(dl, Result, VT);
6630 case ISD::SETUO: Invert =
true; [[fallthrough]];
6639 Result = DAG.
getNOT(dl, Result, VT);
6645 switch (SetCCOpcode) {
6648 if (ST->hasMVEIntegerOps()) {
6651 Invert =
true; [[fallthrough]];
6654 case ISD::SETLT: Swap =
true; [[fallthrough]];
6656 case ISD::SETLE: Swap =
true; [[fallthrough]];
6673 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6676 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6681 Result = DAG.
getNOT(dl, Result, VT);
6706 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6709 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6715 Result = DAG.
getNOT(dl, Result, VT);
6724 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6741 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6752 unsigned OpCmode, Imm;
6763 switch (SplatBitSize) {
6768 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6771 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6776 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6777 if ((SplatBits & ~0xff) == 0) {
6783 if ((SplatBits & ~0xff00) == 0) {
6786 Imm = SplatBits >> 8;
6796 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6797 if ((SplatBits & ~0xff) == 0) {
6803 if ((SplatBits & ~0xff00) == 0) {
6806 Imm = SplatBits >> 8;
6809 if ((SplatBits & ~0xff0000) == 0) {
6812 Imm = SplatBits >> 16;
6815 if ((SplatBits & ~0xff000000) == 0) {
6818 Imm = SplatBits >> 24;
6825 if ((SplatBits & ~0xffff) == 0 &&
6826 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6829 Imm = SplatBits >> 8;
6837 if ((SplatBits & ~0xffffff) == 0 &&
6838 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6841 Imm = SplatBits >> 16;
6857 unsigned ImmMask = 1;
6859 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6860 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6862 }
else if ((SplatBits & BitMask) != 0) {
6871 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6885 EVT VT =
Op.getValueType();
6886 bool IsDouble = (VT == MVT::f64);
6892 if (
ST->genExecuteOnly()) {
6894 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6895 "Unexpected architecture");
6913 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
6918 if (!
ST->hasVFP3Base())
6923 if (IsDouble && !Subtarget->hasFP64())
6930 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
6948 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
6957 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7011 unsigned ExpectedElt = Imm;
7012 for (
unsigned i = 1; i < NumElts; ++i) {
7016 if (ExpectedElt == NumElts)
7019 if (M[i] < 0)
continue;
7020 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7028 bool &ReverseVEXT,
unsigned &Imm) {
7030 ReverseVEXT =
false;
7041 unsigned ExpectedElt = Imm;
7042 for (
unsigned i = 1; i < NumElts; ++i) {
7046 if (ExpectedElt == NumElts * 2) {
7051 if (M[i] < 0)
continue;
7052 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7067 return VT == MVT::v8i8 && M.size() == 8;
7072 if (Mask.size() == Elements * 2)
7073 return Index / Elements;
7074 return Mask[Index] == 0 ? 0 : 1;
7104 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7112 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7114 for (
unsigned j = 0; j < NumElts; j += 2) {
7115 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7116 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7121 if (M.size() == NumElts*2)
7136 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7139 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7141 for (
unsigned j = 0; j < NumElts; j += 2) {
7142 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7143 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7148 if (M.size() == NumElts*2)
7168 if (M.size() != NumElts && M.size() != NumElts*2)
7171 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7173 for (
unsigned j = 0; j < NumElts; ++j) {
7174 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7179 if (M.size() == NumElts*2)
7198 if (M.size() != NumElts && M.size() != NumElts*2)
7201 unsigned Half = NumElts / 2;
7202 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7204 for (
unsigned j = 0; j < NumElts; j += Half) {
7205 unsigned Idx = WhichResult;
7206 for (
unsigned k = 0; k < Half; ++k) {
7207 int MIdx = M[i + j + k];
7208 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7215 if (M.size() == NumElts*2)
7239 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7242 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7244 unsigned Idx = WhichResult * NumElts / 2;
7245 for (
unsigned j = 0; j < NumElts; j += 2) {
7246 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7247 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7253 if (M.size() == NumElts*2)
7272 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7275 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7277 unsigned Idx = WhichResult * NumElts / 2;
7278 for (
unsigned j = 0; j < NumElts; j += 2) {
7279 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7280 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7286 if (M.size() == NumElts*2)
7299 unsigned &WhichResult,
7302 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7303 return ARMISD::VTRN;
7304 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7305 return ARMISD::VUZP;
7306 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7307 return ARMISD::VZIP;
7311 return ARMISD::VTRN;
7313 return ARMISD::VUZP;
7315 return ARMISD::VZIP;
7324 if (NumElts != M.size())
7328 for (
unsigned i = 0; i != NumElts; ++i)
7329 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7338 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7346 int Ofs = Top ? 1 : 0;
7347 int Upper = SingleSource ? 0 : NumElts;
7348 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7349 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7351 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7360 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7369 unsigned Offset = Top ? 0 : 1;
7370 unsigned N = SingleSource ? 0 : NumElts;
7371 for (
unsigned i = 0; i < NumElts; i += 2) {
7372 if (M[i] >= 0 && M[i] != (
int)i)
7374 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7383 if (NumElts != M.size())
7391 unsigned Off0 = rev ? NumElts / 2 : 0;
7392 unsigned Off1 = rev ? 0 : NumElts / 2;
7393 for (
unsigned i = 0; i < NumElts; i += 2) {
7394 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7396 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7412 if (!ST->hasMVEFloatOps())
7417 if (VT != MVT::v8f16)
7438 for (
unsigned i = 1; i < 4; i++) {
7453 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7465 if (!ST->hasMVEFloatOps())
7470 if (VT != MVT::v4f32)
7486 for (
unsigned i = 1; i < 4; i++) {
7497 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7509 Val =
N->getAsZExtVal();
7511 if (ST->isThumb1Only()) {
7512 if (Val <= 255 || ~Val <= 255)
7524 EVT VT =
Op.getValueType();
7526 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7530 unsigned BitsPerBool;
7534 }
else if (NumElts == 4) {
7537 }
else if (NumElts == 8) {
7540 }
else if (NumElts == 16) {
7551 return U.get().isUndef() || U.get() == FirstOp;
7555 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7559 unsigned Bits32 = 0;
7560 for (
unsigned i = 0; i < NumElts; ++i) {
7564 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7566 Bits32 |= BoolMask << (i * BitsPerBool);
7572 for (
unsigned i = 0; i < NumElts; ++i) {
7585 if (!ST->hasMVEIntegerOps())
7589 EVT VT =
Op.getValueType();
7599 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7603 for (
unsigned I = 2;
I < NumElts;
I++) {
7619 switch (
N->getOpcode()) {
7630 return N->getOperand(1).getNode() ==
Op;
7632 switch (
N->getConstantOperandVal(0)) {
7633 case Intrinsic::arm_mve_add_predicated:
7634 case Intrinsic::arm_mve_mul_predicated:
7635 case Intrinsic::arm_mve_qadd_predicated:
7636 case Intrinsic::arm_mve_vhadd:
7637 case Intrinsic::arm_mve_hadd_predicated:
7638 case Intrinsic::arm_mve_vqdmulh:
7639 case Intrinsic::arm_mve_qdmulh_predicated:
7640 case Intrinsic::arm_mve_vqrdmulh:
7641 case Intrinsic::arm_mve_qrdmulh_predicated:
7642 case Intrinsic::arm_mve_vqdmull:
7643 case Intrinsic::arm_mve_vqdmull_predicated:
7645 case Intrinsic::arm_mve_sub_predicated:
7646 case Intrinsic::arm_mve_qsub_predicated:
7647 case Intrinsic::arm_mve_vhsub:
7648 case Intrinsic::arm_mve_hsub_predicated:
7649 return N->getOperand(2).getNode() ==
Op;
7664 EVT VT =
Op.getValueType();
7672 APInt SplatBits, SplatUndef;
7673 unsigned SplatBitSize;
7675 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7682 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7684 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7685 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7686 : SplatBitSize == 16 ? MVT::v8i16
7690 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7693 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7694 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7699 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7703 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7707 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7709 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7713 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7717 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7721 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7727 if (
ST->hasMVEIntegerOps() &&
7728 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7729 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7730 : SplatBitSize == 16 ? MVT::v8i16
7734 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7747 bool isOnlyLowElement =
true;
7748 bool usesOnlyOneValue =
true;
7749 bool hasDominantValue =
false;
7754 DenseMap<SDValue, unsigned> ValueCounts;
7756 for (
unsigned i = 0; i < NumElts; ++i) {
7761 isOnlyLowElement =
false;
7765 unsigned &
Count = ValueCounts[
V];
7768 if (++
Count > (NumElts / 2)) {
7769 hasDominantValue =
true;
7773 if (ValueCounts.
size() != 1)
7774 usesOnlyOneValue =
false;
7775 if (!
Value.getNode() && !ValueCounts.
empty())
7778 if (ValueCounts.
empty())
7790 if (hasDominantValue && EltSize <= 32) {
7799 ConstantSDNode *constIndex;
7806 if (VT !=
Value->getOperand(0).getValueType()) {
7809 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7814 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7819 if (!usesOnlyOneValue) {
7822 for (
unsigned I = 0;
I < NumElts; ++
I) {
7827 Ops.push_back(
Op.getOperand(
I));
7837 assert(FVT == MVT::f32 || FVT == MVT::f16);
7838 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7839 for (
unsigned i = 0; i < NumElts; ++i)
7844 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7848 if (usesOnlyOneValue) {
7851 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7875 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7895 if (EltSize >= 32) {
7901 for (
unsigned i = 0; i < NumElts; ++i)
7915 for (
unsigned i = 0 ; i < NumElts; ++i) {
7934 EVT VT =
Op.getValueType();
7937 struct ShuffleSourceInfo {
7939 unsigned MinElt = std::numeric_limits<unsigned>::max();
7940 unsigned MaxElt = 0;
7950 int WindowScale = 1;
7952 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7960 for (
unsigned i = 0; i < NumElts; ++i) {
7975 SDValue SourceVec =
V.getOperand(0);
7977 if (Source == Sources.
end())
7981 unsigned EltNo =
V.getConstantOperandVal(1);
7988 if (Sources.
size() > 2)
7994 for (
auto &Source : Sources) {
7995 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
7996 if (SrcEltTy.
bitsLT(SmallestEltTy))
7997 SmallestEltTy = SrcEltTy;
7999 unsigned ResMultiplier =
8007 for (
auto &Src : Sources) {
8008 EVT SrcVT = Src.ShuffleVec.getValueType();
8012 if (SrcVTSize == VTSize)
8021 if (SrcVTSize < VTSize) {
8022 if (2 * SrcVTSize != VTSize)
8028 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8032 if (SrcVTSize != 2 * VTSize)
8035 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8040 if (Src.MinElt >= NumSrcElts) {
8045 Src.WindowBase = -NumSrcElts;
8046 }
else if (Src.MaxElt < NumSrcElts) {
8060 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8063 Src.WindowBase = -Src.MinElt;
8070 for (
auto &Src : Sources) {
8071 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8072 if (SrcEltTy == SmallestEltTy)
8075 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8077 Src.WindowBase *= Src.WindowScale;
8082 for (
auto Src : Sources)
8083 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8091 if (
Entry.isUndef())
8100 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8103 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8107 int *LaneMask = &
Mask[i * ResMultiplier];
8109 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8110 ExtractBase += NumElts * (Src - Sources.begin());
8111 for (
int j = 0;
j < LanesDefined; ++
j)
8112 LaneMask[j] = ExtractBase + j;
8118 assert(Sources.size() <= 2 &&
"Too many sources!");
8121 for (
unsigned i = 0; i < Sources.size(); ++i)
8128 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8150 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8170 unsigned PFIndexes[4];
8171 for (
unsigned i = 0; i != 4; ++i) {
8175 PFIndexes[i] = M[i];
8179 unsigned PFTableIndex =
8180 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8182 unsigned Cost = (PFEntry >> 30);
8188 bool ReverseVEXT, isV_UNDEF;
8189 unsigned Imm, WhichResult;
8192 if (EltSize >= 32 ||
8199 else if (Subtarget->hasNEON() &&
8204 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8207 else if (Subtarget->hasMVEIntegerOps() &&
8211 else if (Subtarget->hasMVEIntegerOps() &&
8225 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8226 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8227 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8230 if (LHSID == (1*9+2)*9+3)
return LHS;
8231 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8245 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8248 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8251 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8256 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8261 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8288 for (
int I : ShuffleMask)
8292 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8, V1,
8295 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8, V1, V2,
8301 EVT VT =
Op.getValueType();
8303 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8304 "Expect an v8i16/v16i8 type");
8310 std::vector<int> NewMask;
8314 NewMask.push_back(i);
8344 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8354 if (VT != MVT::v16i1)
8355 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8370 EVT VT =
Op.getValueType();
8374 assert(ST->hasMVEIntegerOps() &&
8375 "No support for vector shuffle of boolean predicates");
8385 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8401 "Expected identical vector type in expanded i1 shuffle!");
8405 PredAsVector2, ShuffleMask);
8410 if (VT == MVT::v2i1) {
8411 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8414 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8416 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8427 EVT VT =
Op.getValueType();
8431 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8432 "Unexpected vector type");
8434 int QuarterSize = NumElts / 4;
8443 for (
int i = 0; i <
Length; i++) {
8444 if (ShuffleMask[Start + i] >= 0) {
8445 if (ShuffleMask[Start + i] %
Length != i)
8447 MovIdx = ShuffleMask[Start + i] /
Length;
8455 for (
int i = 1; i <
Length; i++) {
8456 if (ShuffleMask[Start + i] >= 0 &&
8457 (ShuffleMask[Start + i] /
Length != MovIdx ||
8458 ShuffleMask[Start + i] %
Length != i))
8464 for (
int Part = 0; Part < 4; ++Part) {
8466 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8480 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8485 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8487 for (
int Part = 0; Part < 4; ++Part)
8488 for (
int i = 0; i < QuarterSize; i++)
8490 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8492 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8495 for (
int Part = 0; Part < 4; ++Part)
8511 EVT VT =
Op.getValueType();
8523 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8527 if (Mask[i] != i + BaseOffset) {
8528 if (OffElement == -1)
8534 return NonUndef > 2 && OffElement != -1;
8538 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8540 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8551 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8562 EVT VT =
Op.getValueType();
8566 if (ST->hasMVEIntegerOps() && EltSize == 1)
8577 if (EltSize <= 32) {
8581 if (Lane == -1) Lane = 0;
8592 bool IsScalarToVector =
true;
8595 IsScalarToVector =
false;
8598 if (IsScalarToVector)
8601 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT, V1,
8605 bool ReverseVEXT =
false;
8607 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8610 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V2,
8615 return DAG.
getNode(ARMISD::VREV64, dl, VT, V1);
8617 return DAG.
getNode(ARMISD::VREV32, dl, VT, V1);
8619 return DAG.
getNode(ARMISD::VREV16, dl, VT, V1);
8622 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V1,
8631 unsigned WhichResult = 0;
8632 bool isV_UNDEF =
false;
8633 if (ST->hasNEON()) {
8635 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8642 if (ST->hasMVEIntegerOps()) {
8644 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2, V1,
8647 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V2,
8650 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V1,
8677 }) &&
"Unexpected shuffle index into UNDEF operand!");
8680 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8683 assert((WhichResult == 0) &&
8684 "In-place shuffle of concat can only have one result!");
8693 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8697 for (
bool Top : {
false,
true}) {
8698 for (
bool SingleSource : {
false,
true}) {
8699 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8704 SingleSource ? V1 : V2);
8720 unsigned PFIndexes[4];
8721 for (
unsigned i = 0; i != 4; ++i) {
8722 if (ShuffleMask[i] < 0)
8725 PFIndexes[i] = ShuffleMask[i];
8729 unsigned PFTableIndex =
8730 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8732 unsigned Cost = (PFEntry >> 30);
8738 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8739 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8749 if (EltSize >= 32) {
8757 for (
unsigned i = 0; i < NumElts; ++i) {
8758 if (ShuffleMask[i] < 0)
8762 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8770 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8774 if (ST->hasNEON() && VT == MVT::v8i8)
8778 if (ST->hasMVEIntegerOps())
8787 EVT VecVT =
Op.getOperand(0).getValueType();
8790 assert(ST->hasMVEIntegerOps() &&
8791 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8794 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8795 unsigned Lane =
Op.getConstantOperandVal(2);
8796 unsigned LaneWidth =
8798 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8803 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8816 if (Subtarget->hasMVEIntegerOps() &&
8817 Op.getValueType().getScalarSizeInBits() == 1)
8841 IVecIn, IElt, Lane);
8850 EVT VecVT =
Op.getOperand(0).getValueType();
8853 assert(ST->hasMVEIntegerOps() &&
8854 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8857 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8858 unsigned Lane =
Op.getConstantOperandVal(1);
8859 unsigned LaneWidth =
8881 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8890 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8891 "Unexpected custom CONCAT_VECTORS lowering");
8893 "Unexpected custom CONCAT_VECTORS lowering");
8894 assert(ST->hasMVEIntegerOps() &&
8895 "CONCAT_VECTORS lowering only supported for MVE");
8899 EVT Op2VT = V2.getValueType();
8900 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8901 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8902 "Unexpected i1 concat operations!");
8915 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8920 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8929 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8930 EVT NewVT = NewV.getValueType();
8931 EVT ConcatVT = ConVec.getValueType();
8932 unsigned ExtScale = 1;
8933 if (NewVT == MVT::v2f64) {
8934 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8947 ConVec = ExtractInto(NewV1, ConVec, j);
8948 ConVec = ExtractInto(NewV2, ConVec, j);
8952 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8958 while (ConcatOps.
size() > 1) {
8959 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8962 ConcatOps[
I / 2] = ConcatPair(V1, V2);
8966 return ConcatOps[0];
8971 EVT VT =
Op->getValueType(0);
8977 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
8978 "unexpected CONCAT_VECTORS");
8999 EVT VT =
Op.getValueType();
9005 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9006 assert(ST->hasMVEIntegerOps() &&
9007 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9017 EVT SubVT = MVT::v4i32;
9019 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9029 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
9034 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9043 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9050 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9051 EVT VT =
N->getValueType(0);
9052 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9053 "Expected a vector i1 type!");
9055 EVT FromVT =
Op.getValueType();
9066 if (!Subtarget->hasMVEIntegerOps())
9069 EVT ToVT =
N->getValueType(0);
9112 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9114 EVT FromVT =
N->getOperand(0).getValueType();
9115 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9126 if (!Subtarget->hasMVEIntegerOps())
9131 EVT ToVT =
N->getValueType(0);
9132 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9135 EVT FromVT =
Op.getValueType();
9136 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9150 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9151 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9163 EVT VT =
N->getValueType(0);
9165 SDNode *BVN =
N->getOperand(0).getNode();
9170 unsigned HiElt = 1 - LoElt;
9175 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9191 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9192 SDNode *Elt =
N->getOperand(i).getNode();
9195 unsigned HalfSize = EltSize / 2;
9197 if (!
isIntN(HalfSize,
C->getSExtValue()))
9200 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9239 switch (OrigSimpleTy) {
9255 unsigned ExtOpcode) {
9278 if (ExtendedTy == LD->getMemoryVT())
9279 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9280 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9281 LD->getMemOperand()->getFlags());
9287 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9288 LD->getMemoryVT(), LD->getAlign(),
9289 LD->getMemOperand()->getFlags());
9302 N->getOperand(0)->getValueType(0),
9308 "Expected extending load");
9314 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9323 SDNode *BVN =
N->getOperand(0).getNode();
9325 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9333 EVT VT =
N->getValueType(0);
9339 for (
unsigned i = 0; i != NumElts; ++i) {
9340 const APInt &CInt =
N->getConstantOperandAPInt(i);
9349 unsigned Opcode =
N->getOpcode();
9351 SDNode *N0 =
N->getOperand(0).getNode();
9352 SDNode *N1 =
N->getOperand(1).getNode();
9360 unsigned Opcode =
N->getOpcode();
9362 SDNode *N0 =
N->getOperand(0).getNode();
9363 SDNode *N1 =
N->getOperand(1).getNode();
9373 EVT VT =
Op.getValueType();
9375 "unexpected type for custom-lowering ISD::MUL");
9376 SDNode *N0 =
Op.getOperand(0).getNode();
9377 SDNode *N1 =
Op.getOperand(1).getNode();
9378 unsigned NewOpc = 0;
9382 if (isN0SExt && isN1SExt)
9383 NewOpc = ARMISD::VMULLs;
9387 if (isN0ZExt && isN1ZExt)
9388 NewOpc = ARMISD::VMULLu;
9389 else if (isN1SExt || isN1ZExt) {
9393 NewOpc = ARMISD::VMULLs;
9396 NewOpc = ARMISD::VMULLu;
9400 NewOpc = ARMISD::VMULLu;
9406 if (VT == MVT::v2i64)
9423 "unexpected types for extended operands to VMULL");
9424 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9459 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9493 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9496 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9517 EVT VT =
Op.getValueType();
9518 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9519 "unexpected type for custom-lowering ISD::SDIV");
9526 if (VT == MVT::v8i8) {
9554 EVT VT =
Op.getValueType();
9555 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9556 "unexpected type for custom-lowering ISD::UDIV");
9563 if (VT == MVT::v8i8) {
9602 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9605 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9609 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9629 unsigned Opcode,
bool IsSigned) {
9630 EVT VT0 =
Op.getValue(0).getValueType();
9631 EVT VT1 =
Op.getValue(1).getValueType();
9633 bool InvertCarry = Opcode == ARMISD::SUBE;
9653 EVT VT =
Op.getValueType();
9654 assert((VT == MVT::i32 || VT == MVT::i64) &&
9655 "unexpected type for custom lowering DIV");
9661 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9663 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9670 for (
auto AI : {1, 0}) {
9672 Args.emplace_back(Operand,
9689ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9697 const bool MinSize =
ST.hasMinSize();
9698 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9699 :
ST.hasDivideInARMMode();
9703 if (
N->getOperand(0).getValueType().isVector())
9708 if (!(MinSize && HasDivide))
9721 if (Divisor.
sgt(128))
9729 assert(
Op.getValueType() == MVT::i32 &&
9730 "unexpected type for custom lowering DIV");
9733 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9736 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9742 if (
N->getValueType(0) == MVT::i32)
9743 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9746 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9750void ARMTargetLowering::ExpandDIV_Windows(
9755 assert(
Op.getValueType() == MVT::i64 &&
9756 "unexpected type for custom lowering DIV");
9771std::pair<SDValue, SDValue>
9772ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9778 EVT MemVT =
LD->getMemoryVT();
9779 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9783 unsigned AS =
LD->getAddressSpace();
9784 Align Alignment =
LD->getAlign();
9786 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9789 Alignment <= llvm::Align(2)) {
9792 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9798 Opts, dl,
LD->getChain());
9823 EVT MemVT =
ST->getMemoryVT();
9824 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9828 unsigned AS =
ST->getAddressSpace();
9829 Align Alignment =
ST->getAlign();
9831 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9834 Alignment <= llvm::Align(2)) {
9840 if (
ST->isTruncatingStore())
9844 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9848 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9849 dl,
ST->getChain());
9851 return CallResult.second;
9862 EVT MemVT = LD->getMemoryVT();
9863 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9864 MemVT == MVT::v16i1) &&
9865 "Expected a predicate type!");
9866 assert(MemVT ==
Op.getValueType());
9868 "Expected a non-extending load");
9869 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9883 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9885 LD->getMemOperand());
9891 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9892 if (MemVT != MVT::v16i1)
9901 EVT MemVT =
LD->getMemoryVT();
9903 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9904 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9905 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9906 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9909 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9910 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9915 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9916 auto Pair = LowerAEABIUnalignedLoad(
SDValue(
N, 0), DAG);
9918 Results.push_back(Pair.first);
9919 Results.push_back(Pair.second);
9926 EVT MemVT = ST->getMemoryVT();
9927 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9928 MemVT == MVT::v16i1) &&
9929 "Expected a predicate type!");
9930 assert(MemVT == ST->getValue().getValueType());
9931 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9932 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9937 SDValue Build = ST->getValue();
9938 if (MemVT != MVT::v16i1) {
9951 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9957 ST->getChain(), dl, GRP, ST->getBasePtr(),
9959 ST->getMemOperand());
9965 EVT MemVT =
ST->getMemoryVT();
9967 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9968 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
9969 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9970 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
9971 SDNode *
N =
Op.getNode();
9984 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
9985 MemVT,
ST->getMemOperand());
9986 }
else if (Subtarget->hasMVEIntegerOps() &&
9987 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9988 MemVT == MVT::v16i1))) {
9990 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9991 return LowerAEABIUnalignedStore(
Op, DAG);
9998 (
N->getOpcode() == ARMISD::VMOVIMM &&
10004 MVT VT =
Op.getSimpleValueType();
10006 SDValue PassThru =
N->getPassThru();
10017 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10018 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10019 N->getExtensionType(),
N->isExpandingLoad());
10022 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
10024 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10031 if (!ST->hasMVEIntegerOps())
10035 unsigned BaseOpcode = 0;
10036 switch (
Op->getOpcode()) {
10052 unsigned NumActiveLanes = NumElts;
10054 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10055 NumActiveLanes == 2) &&
10056 "Only expected a power 2 vector size");
10060 while (NumActiveLanes > 4) {
10061 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10063 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10064 NumActiveLanes /= 2;
10068 if (NumActiveLanes == 4) {
10078 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10079 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10080 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10086 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10090 if (EltVT !=
Op->getValueType(0))
10097 if (!ST->hasMVEFloatOps())
10104 if (!ST->hasNEON())
10112 unsigned PairwiseIntrinsic = 0;
10113 switch (
Op->getOpcode()) {
10117 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10120 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10123 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10126 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10132 unsigned NumActiveLanes = NumElts;
10134 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10135 NumActiveLanes == 2) &&
10136 "Only expected a power 2 vector size");
10142 VT =
Lo.getValueType();
10144 NumActiveLanes /= 2;
10148 while (NumActiveLanes > 1) {
10150 NumActiveLanes /= 2;
10157 if (EltVT !=
Op.getValueType()) {
10158 unsigned Extend = 0;
10159 switch (
Op->getOpcode()) {
10171 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10216 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10222 SDLoc dl(V.getNode());
10223 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10233 assert(
N->getValueType(0) == MVT::i64 &&
10234 "AtomicCmpSwap on types less than 64 should be legal");
10243 ARM::CMP_SWAP_64,
SDLoc(
N),
10244 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10263 EVT VT =
Op.getValueType();
10272 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10274 Chain, IsSignaling);
10275 if (!
RHS.getNode()) {
10291 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10293 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10294 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10311 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10314 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10327 if (!IsSigned && Subtarget->isThumb1Only()) {
10345 Sub1Result, Sub1Result, Flags1);
10360 if (
Op.getValueType() != MVT::i32)
10374 unsigned Opcode = ARMISD::SUBC;
10383 bool CanUseAdd =
false;
10399 Opcode = ARMISD::ADDC;
10423 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10424 GTCondValue, Flags);
10428 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10429 LTCondValue, Flags);
10431 if (
Op.getValueType() != MVT::i32)
10439 switch (
Op.getOpcode()) {
10471 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10475 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10476 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10498 return LowerSET_FPMODE(
Op, DAG);
10500 return LowerRESET_FPMODE(
Op, DAG);
10504 !
Op.getValueType().isVector())
10505 return LowerDIV_Windows(
Op, DAG,
true);
10509 !
Op.getValueType().isVector())
10510 return LowerDIV_Windows(
Op, DAG,
false);
10526 return LowerALUO(
Op, DAG);
10534 EVT MemVT = LD->getMemoryVT();
10535 if (Subtarget->hasMVEIntegerOps() &&
10536 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10537 MemVT == MVT::v16i1))
10540 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10546 return LowerSTORE(
Op, DAG, Subtarget);
10571 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10580 return LowerSPONENTRY(
Op, DAG);
10582 return LowerFP_TO_BF16(
Op, DAG);
10583 case ARMISD::WIN__DBZCHK:
return SDValue();
10586 return LowerCMP(
Op, DAG);
10588 return LowerABS(
Op, DAG);
10593 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10594 Op.getOperand(1).getValueType() == MVT::bf16) &&
10595 "Expected custom lowering of rounding operations only for f16");
10598 {
Op.getOperand(0),
Op.getOperand(1)});
10599 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10600 {Ext.getValue(1), Ext.getValue(0)});
10607 unsigned IntNo =
N->getConstantOperandVal(0);
10609 if (IntNo == Intrinsic::arm_smlald)
10610 Opc = ARMISD::SMLALD;
10611 else if (IntNo == Intrinsic::arm_smlaldx)
10612 Opc = ARMISD::SMLALDX;
10613 else if (IntNo == Intrinsic::arm_smlsld)
10614 Opc = ARMISD::SMLSLD;
10615 else if (IntNo == Intrinsic::arm_smlsldx)
10616 Opc = ARMISD::SMLSLDX;
10622 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10626 N->getOperand(1),
N->getOperand(2),
10638 switch (
N->getOpcode()) {
10645 Res = ExpandBITCAST(
N, DAG, Subtarget);
10654 Res = LowerREM(
N, DAG);
10658 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10675 "can only expand DIV on Windows");
10687 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10716 "ROPI/RWPI not currently supported with SjLj");
10725 bool isThumb = Subtarget->isThumb();
10726 bool isThumb2 = Subtarget->
isThumb2();
10729 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10735 : &ARM::GPRRegClass;
10841 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10844 MachineRegisterInfo *MRI = &MF->
getRegInfo();
10848 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10849 : &ARM::GPRnopcRegClass;
10853 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10854 unsigned MaxCSNum = 0;
10855 for (MachineBasicBlock &BB : *MF) {
10861 for (MachineInstr &
II : BB) {
10862 if (!
II.isEHLabel())
10865 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10866 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10868 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10869 for (
unsigned Idx : CallSiteIdxs) {
10870 CallSiteNumToLPad[Idx].push_back(&BB);
10871 MaxCSNum = std::max(MaxCSNum, Idx);
10878 std::vector<MachineBasicBlock*> LPadList;
10879 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10880 LPadList.reserve(CallSiteNumToLPad.
size());
10881 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10882 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10883 for (MachineBasicBlock *
MBB : MBBList) {
10884 LPadList.push_back(
MBB);
10889 assert(!LPadList.empty() &&
10890 "No landing pad destinations for the dispatch jump table!");
10893 MachineJumpTableInfo *JTI =
10900 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10903 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10905 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10908 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10912 MF->insert(MF->end(), DispatchBB);
10913 MF->insert(MF->end(), DispContBB);
10914 MF->insert(MF->end(), TrapBB);
10918 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10920 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10924 MachineInstrBuilder MIB;
10925 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10927 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10937 unsigned NumLPads = LPadList.size();
10938 if (Subtarget->isThumb2()) {
10940 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10946 if (NumLPads < 256) {
10947 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10949 .
addImm(LPadList.size())
10953 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10954 .
addImm(NumLPads & 0xFFFF)
10957 unsigned VReg2 = VReg1;
10958 if ((NumLPads & 0xFFFF0000) != 0) {
10960 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10966 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
10972 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
10978 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
10983 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
10990 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
10994 }
else if (Subtarget->isThumb()) {
10996 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11002 if (NumLPads < 256) {
11003 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11008 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11013 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11014 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11017 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11021 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11027 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11033 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11040 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11045 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11051 MachineMemOperand *JTMMOLd =
11056 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11062 unsigned NewVReg6 = NewVReg5;
11063 if (IsPositionIndependent) {
11065 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11072 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11077 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11083 if (NumLPads < 256) {
11084 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11088 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11090 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11091 .
addImm(NumLPads & 0xFFFF)
11094 unsigned VReg2 = VReg1;
11095 if ((NumLPads & 0xFFFF0000) != 0) {
11097 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11103 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11108 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11113 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11114 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11117 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11122 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11134 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11140 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11144 MachineMemOperand *JTMMOLd =
11148 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11155 if (IsPositionIndependent) {
11156 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11161 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11168 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11169 for (MachineBasicBlock *CurMBB : LPadList) {
11170 if (SeenMBBs.
insert(CurMBB).second)
11177 for (MachineBasicBlock *BB : InvokeBBs) {
11181 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11182 while (!Successors.empty()) {
11183 MachineBasicBlock *SMBB = Successors.pop_back_val();
11185 BB->removeSuccessor(SMBB);
11191 BB->normalizeSuccProbs();
11198 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11199 if (!
II->isCall())
continue;
11201 DenseSet<unsigned> DefRegs;
11203 OI =
II->operands_begin(), OE =
II->operands_end();
11205 if (!OI->isReg())
continue;
11206 DefRegs.
insert(OI->getReg());
11209 MachineInstrBuilder MIB(*MF, &*
II);
11211 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11212 unsigned Reg = SavedRegs[i];
11213 if (Subtarget->isThumb2() &&
11214 !ARM::tGPRRegClass.contains(
Reg) &&
11215 !ARM::hGPRRegClass.contains(
Reg))
11217 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11219 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11231 for (MachineBasicBlock *MBBLPad : MBBLPads)
11232 MBBLPad->setIsEHPad(
false);
11235 MI.eraseFromParent();
11248static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11250 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11251 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11253 return LdSize == 4 ? ARM::tLDRi
11254 : LdSize == 2 ? ARM::tLDRHi
11255 : LdSize == 1 ? ARM::tLDRBi : 0;
11257 return LdSize == 4 ? ARM::t2LDR_POST
11258 : LdSize == 2 ? ARM::t2LDRH_POST
11259 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11260 return LdSize == 4 ? ARM::LDR_POST_IMM
11261 : LdSize == 2 ? ARM::LDRH_POST
11262 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11267static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11269 return StSize == 16 ? ARM::VST1q32wb_fixed
11270 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11272 return StSize == 4 ? ARM::tSTRi
11273 : StSize == 2 ? ARM::tSTRHi
11274 : StSize == 1 ? ARM::tSTRBi : 0;
11276 return StSize == 4 ? ARM::t2STR_POST
11277 : StSize == 2 ? ARM::t2STRH_POST
11278 : StSize == 1 ? ARM::t2STRB_POST : 0;
11279 return StSize == 4 ? ARM::STR_POST_IMM
11280 : StSize == 2 ? ARM::STRH_POST
11281 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11288 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11289 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11290 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11291 assert(LdOpc != 0 &&
"Should have a load opcode");
11298 }
else if (IsThumb1) {
11304 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11309 }
else if (IsThumb2) {
11329 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11330 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11331 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11332 assert(StOpc != 0 &&
"Should have a store opcode");
11334 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11339 }
else if (IsThumb1) {
11346 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11351 }
else if (IsThumb2) {
11352 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11358 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11373 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11379 unsigned SizeVal =
MI.getOperand(2).getImm();
11380 unsigned Alignment =
MI.getOperand(3).getImm();
11384 MachineRegisterInfo &MRI = MF->
getRegInfo();
11385 unsigned UnitSize = 0;
11386 const TargetRegisterClass *TRC =
nullptr;
11387 const TargetRegisterClass *VecTRC =
nullptr;
11389 bool IsThumb1 = Subtarget->isThumb1Only();
11390 bool IsThumb2 = Subtarget->isThumb2();
11391 bool IsThumb = Subtarget->isThumb();
11393 if (Alignment & 1) {
11395 }
else if (Alignment & 2) {
11400 Subtarget->hasNEON()) {
11401 if ((Alignment % 16 == 0) && SizeVal >= 16)
11403 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11412 bool IsNeon = UnitSize >= 8;
11413 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11415 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11416 : UnitSize == 8 ? &ARM::DPRRegClass
11419 unsigned BytesLeft = SizeVal % UnitSize;
11420 unsigned LoopSize = SizeVal - BytesLeft;
11422 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11426 unsigned srcIn = src;
11427 unsigned destIn = dest;
11428 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11433 IsThumb1, IsThumb2);
11435 IsThumb1, IsThumb2);
11443 for (
unsigned i = 0; i < BytesLeft; i++) {
11448 IsThumb1, IsThumb2);
11450 IsThumb1, IsThumb2);
11454 MI.eraseFromParent();
11480 MF->
insert(It, loopMBB);
11481 MF->
insert(It, exitMBB);
11484 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11495 if (Subtarget->useMovt()) {
11496 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11499 }
else if (Subtarget->genExecuteOnly()) {
11500 assert(IsThumb &&
"Non-thumb expected to have used movt");
11509 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11510 MachineMemOperand *CPMMO =
11534 MachineBasicBlock *entryBB = BB;
11549 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11557 IsThumb1, IsThumb2);
11559 IsThumb1, IsThumb2);
11563 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11569 MachineInstrBuilder MIB =
11571 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11580 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11589 auto StartOfExit = exitMBB->
begin();
11593 unsigned srcIn = srcLoop;
11594 unsigned destIn = destLoop;
11595 for (
unsigned i = 0; i < BytesLeft; i++) {
11599 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11600 IsThumb1, IsThumb2);
11601 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11602 IsThumb1, IsThumb2);
11607 MI.eraseFromParent();
11615 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11618 assert(TM.getTargetTriple().isOSWindows() &&
11619 "__chkstk is only supported on Windows");
11620 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11640 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11641 if (ChkStkLibcall == RTLIB::Unsupported)
11645 switch (TM.getCodeModel()) {
11687 MI.eraseFromParent();
11696 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11711 .
addReg(
MI.getOperand(0).getReg())
11719 MI.eraseFromParent();
11743 if (miI == BB->
end()) {
11745 if (Succ->isLiveIn(ARM::CPSR))
11751 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11764 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11771 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11778 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11781 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11782 .
addUse(TotalIterationsReg)
11789 return TotalIterationsReg;
11800 Register TotalIterationsReg,
bool IsMemcpy) {
11809 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11819 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11827 Register RemainingLoopIterationsReg =
11829 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11830 .
addUse(TotalIterationsReg)
11832 .
addUse(RemainingLoopIterationsReg)
11838 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11839 .
addUse(ElementCountReg)
11841 .
addUse(RemainingElementsReg)
11846 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11847 .
addUse(PredCounterPhiReg)
11852 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11853 .
addUse(PredCounterPhiReg)
11862 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11871 SrcValueReg = OpSrcReg;
11873 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11884 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11885 .
addUse(LoopCounterPhiReg)
11888 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11889 .
addUse(RemainingLoopIterationsReg)
11907 "Invalid call instruction for a KCFI check");
11910 switch (
MBBI->getOpcode()) {
11913 case ARM::BLX_pred:
11914 case ARM::BLX_noip:
11915 case ARM::BLX_pred_noip:
11917 TargetOp = &
MBBI->getOperand(0);
11919 case ARM::TCRETURNri:
11920 case ARM::TCRETURNrinotr12:
11921 case ARM::TAILJMPr:
11922 case ARM::TAILJMPr4:
11923 TargetOp = &
MBBI->getOperand(0);
11929 case ARM::tBLXr_noip:
11930 case ARM::tBX_CALL:
11931 TargetOp = &
MBBI->getOperand(2);
11934 case ARM::tTAILJMPr:
11935 TargetOp = &
MBBI->getOperand(0);
11941 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11945 unsigned KCFICheckOpcode;
11946 if (Subtarget->isThumb()) {
11947 if (Subtarget->isThumb2()) {
11948 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11950 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11953 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11967 bool isThumb2 = Subtarget->isThumb2();
11968 switch (
MI.getOpcode()) {
11975 case ARM::tLDR_postidx: {
11979 .
add(
MI.getOperand(2))
11980 .
add(
MI.getOperand(3))
11981 .
add(
MI.getOperand(4))
11982 .
add(
MI.getOperand(0))
11984 MI.eraseFromParent();
11988 case ARM::MVE_MEMCPYLOOPINST:
11989 case ARM::MVE_MEMSETLOOPINST: {
12019 Register OpDestReg =
MI.getOperand(0).getReg();
12020 Register OpSrcReg =
MI.getOperand(1).getReg();
12021 Register OpSizeReg =
MI.getOperand(2).getReg();
12041 if (TpExit == BB) {
12043 "block containing memcpy/memset Pseudo");
12053 genTPEntry(TpEntry, TpLoopBody, TpExit, OpSizeReg,
TII, dl, MRI);
12056 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12058 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12061 Properties.resetNoPHIs();
12073 MI.eraseFromParent();
12083 case ARM::t2STR_preidx:
12084 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12086 case ARM::t2STRB_preidx:
12087 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12089 case ARM::t2STRH_preidx:
12090 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12093 case ARM::STRi_preidx:
12094 case ARM::STRBi_preidx: {
12095 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12096 : ARM::STRB_PRE_IMM;
12098 unsigned Offset =
MI.getOperand(4).getImm();
12106 .
add(
MI.getOperand(0))
12107 .
add(
MI.getOperand(1))
12108 .
add(
MI.getOperand(2))
12110 .
add(
MI.getOperand(5))
12111 .
add(
MI.getOperand(6))
12113 MI.eraseFromParent();
12116 case ARM::STRr_preidx:
12117 case ARM::STRBr_preidx:
12118 case ARM::STRH_preidx: {
12120 switch (
MI.getOpcode()) {
12122 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12123 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12124 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12129 MI.eraseFromParent();
12133 case ARM::tMOVCCr_pseudo: {
12151 F->insert(It, copy0MBB);
12152 F->insert(It, sinkMBB);
12155 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12161 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12177 .
addImm(
MI.getOperand(3).getImm())
12178 .
addReg(
MI.getOperand(4).getReg());
12193 .
addReg(
MI.getOperand(1).getReg())
12195 .
addReg(
MI.getOperand(2).getReg())
12198 MI.eraseFromParent();
12203 case ARM::BCCZi64: {
12209 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12214 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12218 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12224 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12228 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12238 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12247 MI.eraseFromParent();
12251 case ARM::Int_eh_sjlj_setjmp:
12252 case ARM::Int_eh_sjlj_setjmp_nofp:
12253 case ARM::tInt_eh_sjlj_setjmp:
12254 case ARM::t2Int_eh_sjlj_setjmp:
12255 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12258 case ARM::Int_eh_sjlj_setup_dispatch:
12259 EmitSjLjDispatchBlock(
MI, BB);
12261 case ARM::COPY_STRUCT_BYVAL_I32:
12263 return EmitStructByval(
MI, BB);
12264 case ARM::WIN__CHKSTK:
12265 return EmitLowered__chkstk(
MI, BB);
12266 case ARM::WIN__DBZCHK:
12267 return EmitLowered__dbzchk(
MI, BB);
12283 if (!
Node->hasAnyUseOfValue(0)) {
12284 MI.getOperand(0).setIsDead(
true);
12286 if (!
Node->hasAnyUseOfValue(1)) {
12287 MI.getOperand(1).setIsDead(
true);
12291 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12293 : &ARM::GPRRegClass);
12300 if (
MI.getOpcode() == ARM::MEMCPY) {
12321 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12322 &&
"converted opcode should be the same except for cc_out"
12323 " (and, on Thumb1, pred)");
12331 if (Subtarget->isThumb1Only()) {
12332 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12333 MI.addOperand(
MI.getOperand(1));
12334 MI.removeOperand(1);
12338 for (
unsigned i =
MI.getNumOperands(); i--;) {
12340 if (
op.isReg() &&
op.isUse()) {
12343 MI.tieOperands(DefIdx, i);
12351 ccOutIdx =
MCID->getNumOperands() - 1;
12353 ccOutIdx =
MCID->getNumOperands() - 1;
12357 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12358 assert(!NewOpc &&
"Optional cc_out operand required");
12363 bool definesCPSR =
false;
12364 bool deadCPSR =
false;
12365 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12369 definesCPSR =
true;
12372 MI.removeOperand(i);
12376 if (!definesCPSR) {
12377 assert(!NewOpc &&
"Optional cc_out operand required");
12380 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12382 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12383 "expect uninitialized optional cc_out operand");
12385 if (!Subtarget->isThumb1Only())
12421 switch (
N->getOpcode()) {
12422 default:
return false;
12424 CC =
N->getOperand(0);
12446 EVT VT =
N->getValueType(0);
12447 CC =
N->getOperand(0);
12494 EVT VT =
N->getValueType(0);
12497 bool SwapSelectOps;
12499 NonConstantVal, DAG))
12505 OtherOp, NonConstantVal);
12511 CCOp, TrueVal, FalseVal);
12531 if (
N->getOpcode() == ARMISD::VUZP)
12535 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12550 if (!
N->getValueType(0).is64BitVector())
12558 EVT VT =
N->getValueType(0);
12597 EVT VT =
N->getValueType(0);
12603 Opcode = Intrinsic::arm_neon_vpaddls;
12605 Opcode = Intrinsic::arm_neon_vpaddlu;
12633 EVT VT =
N->getValueType(0);
12648 unsigned nextIndex = 0;
12699 Ops.push_back(Vec);
12716 return DAG.
getNode(ExtOp, dl, VT, tmp);
12747 if (SRA.getOpcode() !=
ISD::SRA) {
12754 if (Const->getZExtValue() != 31)
12759 if (SRA.getOperand(0) !=
Mul)
12763 SDLoc dl(AddcNode);
12764 unsigned Opcode = 0;
12769 Opcode = ARMISD::SMLALBB;
12770 Op0 =
Mul.getOperand(0);
12771 Op1 =
Mul.getOperand(1);
12773 Opcode = ARMISD::SMLALBT;
12774 Op0 =
Mul.getOperand(0);
12775 Op1 =
Mul.getOperand(1).getOperand(0);
12777 Opcode = ARMISD::SMLALTB;
12778 Op0 =
Mul.getOperand(0).getOperand(0);
12779 Op1 =
Mul.getOperand(1);
12781 Opcode = ARMISD::SMLALTT;
12782 Op0 =
Mul->getOperand(0).getOperand(0);
12783 Op1 =
Mul->getOperand(1).getOperand(0);
12799 SDValue resNode(AddcNode, 0);
12827 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12828 "Expect an ADDE or SUBE");
12832 "ADDE node has the wrong inputs");
12836 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12837 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12838 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12839 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12851 "Expect ADDC with two result values. First: i32");
12855 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12871 bool IsLeftOperandMUL =
false;
12876 IsLeftOperandMUL =
true;
12887 SDValue *LowAddSub =
nullptr;
12890 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12893 if (IsLeftOperandMUL)
12894 HiAddSub = &AddeSubeOp1;
12896 HiAddSub = &AddeSubeOp0;
12901 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12902 LoMul = &AddcSubcOp0;
12903 LowAddSub = &AddcSubcOp1;
12905 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12906 LoMul = &AddcSubcOp1;
12907 LowAddSub = &AddcSubcOp0;
12915 if (AddcSubcNode == HiAddSub->getNode() ||
12931 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12936 Ops.push_back(*HiAddSub);
12937 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12938 FinalOpc = ARMISD::SMMLSR;
12940 FinalOpc = ARMISD::SMMLAR;
12945 return SDValue(AddeSubeNode, 0);
12946 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12952 Ops.push_back(*LowAddSub);
12953 Ops.push_back(*HiAddSub);
12966 return SDValue(AddeSubeNode, 0);
12978 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12983 if (AddcNode->
getOpcode() != ARMISD::ADDC)
12987 SDNode *UmlalNode =
nullptr;
13026 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13031 SDNode* AddcNode =
N->getOperand(2).getNode();
13032 SDNode* AddeNode =
N->getOperand(3).getNode();
13033 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
13034 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
13040 {N->getOperand(0), N->getOperand(1),
13041 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13051 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13055 if (
LHS->getOpcode() == ARMISD::ADDE &&
13065 int32_t imm =
C->getSExtValue();
13066 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13069 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13071 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13086 int64_t imm =
C->getSExtValue();
13095 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13097 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13098 N->getOperand(0),
RHS,
N->getOperand(2));
13110 if (!Subtarget->hasMVEIntegerOps())
13123 SetCC =
N->getOperand(0);
13127 TrueVal =
N->getOperand(1);
13128 FalseVal =
N->getOperand(2);
13130 LHS =
N->getOperand(0);
13131 RHS =
N->getOperand(1);
13133 TrueVal =
N->getOperand(2);
13134 FalseVal =
N->getOperand(3);
13139 unsigned int Opcode = 0;
13143 Opcode = ARMISD::VMINVu;
13149 Opcode = ARMISD::VMINVs;
13155 Opcode = ARMISD::VMAXVu;
13161 Opcode = ARMISD::VMAXVs;
13168 switch (TrueVal->getOpcode()) {
13187 if (TrueVal !=
LHS || FalseVal !=
RHS)
13190 EVT LeftType =
LHS->getValueType(0);
13191 EVT RightType =
RHS->getValueType(0);
13194 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13198 if (VectorScalarType != MVT::i32)
13206 if (VectorScalarType != MVT::i32)
13219 EVT VT =
N->getValueType(0);
13227 Shft =
N->getOperand(0);
13234 Cmp.getOperand(0) !=
N->getOperand(1) ||
13235 Cmp.getOperand(1) !=
N->getOperand(2))
13237 Shft =
N->getOperand(1);
13249 ScalarType = MVT::i8;
13252 case (1 << 15) - 1:
13253 ScalarType = MVT::i16;
13256 case (1ULL << 31) - 1:
13257 ScalarType = MVT::i32;
13288 unsigned LegalLanes = 128 / (ShftAmt + 1);
13300 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13301 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13302 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13303 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13312 for (
unsigned I = 0;
I < NumParts; ++
I) {
13319 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13329 if (!Subtarget->hasMVEIntegerOps())
13344 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13354 if (!Const || !Const->isOne())
13372 EVT VT =
N->getValueType(0);
13374 if (!Subtarget->hasMVEIntegerOps() ||
13403 Opc = Intrinsic::arm_mve_vctp64;
13406 Opc = Intrinsic::arm_mve_vctp32;
13409 Opc = Intrinsic::arm_mve_vctp16;
13412 Opc = Intrinsic::arm_mve_vctp8;
13466 EVT VT =
N->getValueType(0);
13472 switch (
Op.getOpcode()) {
13474 case ARMISD::VADDVs:
13475 case ARMISD::VADDVu:
13476 case ARMISD::VMLAVs:
13477 case ARMISD::VMLAVu:
13497 unsigned N0RedOp = 0;
13504 unsigned N1RedOp = 0;
13518 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13520 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13527 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13551 if (!BaseLocDecomp0.getBase() ||
13552 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13553 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13555 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13557 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13567 if (IsBefore < 0) {
13570 }
else if (IsBefore > 0) {
13583 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13593 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13603 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13605 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13612 if (!Subtarget->hasMVEIntegerOps())
13618 EVT VT =
N->getValueType(0);
13623 if (VT != MVT::i64)
13634 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13654 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13663 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13665 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13667 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13669 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13671 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13673 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13675 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13677 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13679 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13681 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13683 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13685 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13687 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13689 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13691 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13693 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13703 "Expected shift op");
13705 SDValue ShiftLHS =
N->getOperand(0);
13719 if (Subtarget->isThumb1Only()) {
13730 if (Const->getAPIntValue().ult(256))
13733 Const->getAPIntValue().sgt(-256))
13749 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13750 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13751 "Expected XOR(SHIFT) pattern");
13756 if (XorC && ShiftC) {
13757 unsigned MaskIdx, MaskLen;
13758 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13759 unsigned ShiftAmt = ShiftC->getZExtValue();
13760 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13761 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13762 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13763 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13773 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13775 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13776 "Expected shift-shift mask");
13778 if (!Subtarget->isThumb1Only())
13781 EVT VT =
N->getValueType(0);
13789 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13791 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13796 if (!Subtarget->hasNEON()) {
13797 if (Subtarget->isThumb1Only())
13811 return Subtarget->hasVFP2Base();
13813 return Subtarget->hasVFP2Base();
13815 return Subtarget->hasFP64();
13818 return Subtarget->hasMVEFloatOps();
13847 if (ST->isThumb() && ST->isThumb1Only())
13851 for (
auto *U :
N->users()) {
13852 switch(U->getOpcode()) {
13870 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13871 U->getOperand(1).getOpcode() ==
ISD::SHL)
13881 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13888 if (!C1ShlC2 || !C2)
13891 APInt C2Int = C2->getAPIntValue();
13892 APInt C1Int = C1ShlC2->getAPIntValue();
13894 if (C2Int.
uge(C2Width))
13900 if ((C1Int & Mask) != C1Int)
13907 auto LargeImm = [](
const APInt &Imm) {
13908 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13909 return Imm.getBitWidth() - Zeros > 8;
13912 if (LargeImm(C1Int) || LargeImm(C2Int))
13924 SHL.dump();
N->dump());
13985 if (
Op.hasOneUse() && ShiftAmt &&
13986 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
14044 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14065 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14086 if (!Subtarget->hasVMLxForwarding())
14105 EVT VT =
N->getValueType(0);
14116 EVT VT =
N->getValueType(0);
14117 if (VT != MVT::v2i64)
14128 return Op->getOperand(0);
14142 And =
And->getOperand(0);
14147 Mask = Mask->getOperand(0);
14150 Mask.getValueType() != MVT::v4i32)
14156 return And->getOperand(0);
14161 if (
SDValue Op0 = IsSignExt(N0)) {
14162 if (
SDValue Op1 = IsSignExt(N1)) {
14163 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14164 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14165 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14168 if (
SDValue Op0 = IsZeroExt(N0)) {
14169 if (
SDValue Op1 = IsZeroExt(N1)) {
14170 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14171 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14172 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14184 EVT VT =
N->getValueType(0);
14185 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14196 if (VT != MVT::i32)
14203 int64_t MulAmt =
C->getSExtValue();
14206 ShiftAmt = ShiftAmt & (32 - 1);
14211 MulAmt >>= ShiftAmt;
14272 if (
N->getValueType(0) != MVT::i32)
14281 if (C1 == 255 || C1 == 65535)
14284 SDNode *N0 =
N->getOperand(0).getNode();
14298 if (!C2 || C2 >= 32)
14342 if (Trailing == C2 && C2 + C3 < 32) {
14355 if (Leading == C2 && C2 + C3 < 32) {
14383 EVT VT =
N->getValueType(0);
14387 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14390 APInt SplatBits, SplatUndef;
14391 unsigned SplatBitSize;
14393 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14394 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14395 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14396 SplatBitSize == 64) {
14403 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14405 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14430 if (!Subtarget->hasV6Ops() ||
14431 (Subtarget->isThumb() &&
14432 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14435 SDValue SRL = OR->getOperand(0);
14436 SDValue SHL = OR->getOperand(1);
14439 SRL = OR->getOperand(1);
14440 SHL = OR->getOperand(0);
14447 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14451 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14452 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14453 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14472 unsigned Opcode = 0;
14473 if (
isS16(OpS16, DAG))
14474 Opcode = ARMISD::SMULWB;
14476 Opcode = ARMISD::SMULWT;
14491 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14494 EVT VT =
N->getValueType(0);
14509 if (VT != MVT::i32)
14522 if (Mask == 0xffff)
14529 if ((Val & ~Mask) != Val)
14535 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14554 (Mask == ~Mask2)) {
14557 if (Subtarget->hasDSP() &&
14558 (Mask == 0xffff || Mask == 0xffff0000))
14564 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14571 (~Mask == Mask2)) {
14574 if (Subtarget->hasDSP() &&
14575 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14631 if (
N->getOpcode() == ARMISD::VCMP)
14633 else if (
N->getOpcode() == ARMISD::VCMPZ)
14641 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14648 EVT VT =
N->getValueType(0);
14653 auto IsFreelyInvertable = [&](
SDValue V) {
14654 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14660 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14678 if (AndOp.getOpcode() !=
ISD::AND)
14682 SDValue Mask = AndOp.getOperand(1);
14692 bool IsShiftRight =
false;
14695 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14696 IsShiftRight =
true;
14699 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14707 APInt RequiredMask = IsShiftRight
14710 if (MaskBits != RequiredMask)
14713 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14723 EVT VT =
N->getValueType(0);
14729 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14730 VT == MVT::v8i1 || VT == MVT::v16i1))
14733 APInt SplatBits, SplatUndef;
14734 unsigned SplatBitSize;
14736 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14737 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14738 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14739 SplatBitSize == 64) {
14746 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14748 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14768 (Subtarget->hasMVEIntegerOps() &&
14769 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14772 return ShiftInsert;
14776 return ShiftInsert;
14790 unsigned SplatBitSize;
14793 APInt SplatBits0, SplatBits1;
14797 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14798 HasAnyUndefs) && !HasAnyUndefs) {
14799 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14800 HasAnyUndefs) && !HasAnyUndefs) {
14805 SplatBits0 == ~SplatBits1) {
14813 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14835 EVT VT =
N->getValueType(0);
14850 if (Subtarget->hasMVEIntegerOps()) {
14878 assert(
N->getOpcode() == ARMISD::BFI);
14881 ToMask =
~N->getConstantOperandAPInt(2);
14901 unsigned LastActiveBitInA =
A.countr_zero();
14902 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14903 return LastActiveBitInA - 1 == FirstActiveBitInB;
14908 APInt ToMask, FromMask;
14913 if (V.getOpcode() != ARMISD::BFI)
14916 APInt NewToMask, NewFromMask;
14918 if (NewFrom != From)
14922 if ((NewToMask & ToMask).getBoolValue())
14947 unsigned InvMask =
N->getConstantOperandVal(2);
14951 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14952 "undefined behavior");
14953 unsigned Mask = (1u << Width) - 1;
14955 if ((Mask & (~Mask2)) == 0)
14957 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14964 APInt ToMask1, FromMask1;
14967 APInt ToMask2, FromMask2;
14973 APInt NewFromMask = FromMask1 | FromMask2;
14974 APInt NewToMask = ToMask1 | ToMask2;
14976 EVT VT =
N->getValueType(0);
14979 if (NewFromMask[0] == 0)
14982 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
14990 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
14991 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14992 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14994 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14998 EVT VT =
N->getValueType(0);
15001 N->getOperand(1),
N->getOperand(2));
15013 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
15015 SDValue CSInc = Cmp->getOperand(0);
15025 if (CSInc.
getOpcode() == ARMISD::CSINC &&
15065 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15066 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15069 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15071 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15084 SDValue InDouble =
N->getOperand(0);
15085 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15099 SDValue BasePtr = LD->getBasePtr();
15101 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15102 LD->getAlign(), LD->getMemOperand()->getFlags());
15108 LD->getPointerInfo().getWithOffset(4),
15110 LD->getMemOperand()->getFlags());
15129 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15143 if (!Subtarget->
isLittle() && BVSwap)
15161 if (!Subtarget->
isLittle() && BVSwap)
15180 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15193 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15206 if (Copy.getValueType() == MVT::f32 &&
15208 bool HasGlue = Copy->getNumOperands() == 3;
15209 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15210 HasGlue ? Copy->getOperand(2) :
SDValue()};
15211 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15230 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15231 LN0->getMemoryVT() == MVT::i16) {
15234 LN0->getBasePtr(), LN0->getMemOperand());
15252 EVT VT =
N->getValueType(0);
15286 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15287 for (
unsigned i = 0; i < NumElts; ++i) {
15288 SDNode *Elt =
N->getOperand(i).getNode();
15305 if (
N->getNumOperands() == 2)
15311 EVT VT =
N->getValueType(0);
15317 for (
unsigned i = 0; i < NumElts; ++i) {
15343 EVT VT =
N->getValueType(0);
15351 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15356 Use->getValueType(0).isFloatingPoint())
15364 unsigned NumOfBitCastedElts = 0;
15366 unsigned NumOfRelevantElts = NumElts;
15367 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15372 ++NumOfBitCastedElts;
15376 --NumOfRelevantElts;
15380 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15398 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15403 V->getOperand(0).getValueType() == MVT::i32)
15405 V = V.getOperand(0);
15422 EVT VT =
N->getValueType(0);
15427 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15429 if (
Op->getOperand(0).getValueType() == VT)
15430 return Op->getOperand(0);
15431 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15438 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15445 if (
Op.getValueType() == MVT::i32) {
15456 EVT VT =
N->getValueType(0);
15461 if (ST->isLittle())
15465 if (
Op.getValueType() == VT)
15472 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15474 if (
Op->getOperand(0).getValueType() == VT)
15475 return Op->getOperand(0);
15476 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15484 if (!Subtarget->hasMVEIntegerOps())
15487 EVT VT =
N->getValueType(0);
15495 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15501 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15505 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15518 EVT VT =
N->getValueType(0);
15519 SDNode *Elt =
N->getOperand(1).getNode();
15534 Vec, V,
N->getOperand(2));
15544 EVT VT =
N->getValueType(0);
15572 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15573 isa<ConstantSDNode>(V->getOperand(1)) &&
15574 V->getConstantOperandVal(1) == Lane + 1 &&
15575 V->getOperand(0).getResNo() == ResNo;
15577 if (OtherIt == Op0->
users().
end())
15582 SDValue OtherExt(*OtherIt, 0);
15594 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15597 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15607 EVT VT =
N->getValueType(0);
15611 if (Op0->
getOpcode() == ARMISD::VDUP) {
15613 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15614 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15615 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15616 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15617 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15620 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15621 X =
X->getOperand(0);
15622 if (
X.getValueType() == VT)
15630 return Op0.
getOperand(
N->getConstantOperandVal(1));
15640 unsigned Offset =
N->getConstantOperandVal(1);
15642 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15652 unsigned Idx =
N->getConstantOperandVal(1);
15666 EVT VT =
N->getValueType(0);
15669 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15671 Op.getOperand(0).getValueType().getScalarType())
15672 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15681 SDValue SubVec =
N->getOperand(1);
15682 uint64_t IdxVal =
N->getConstantOperandVal(2);
15693 if (IdxVal == 0 && Vec.
isUndef())
15699 (IdxVal != 0 && IdxVal != NumSubElts))
15730 ARMISD::VMOVN,
DL, VT,
15736 ARMISD::VMOVN,
DL, VT,
15772 EVT VT =
N->getValueType(0);
15783 unsigned HalfElts = NumElts/2;
15785 for (
unsigned n = 0; n < NumElts; ++n) {
15788 if (MaskElt < (
int)HalfElts)
15790 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15791 NewElt = HalfElts + MaskElt - NumElts;
15834 bool SimpleConstIncOnly,
15842 bool isLoadOp =
true;
15843 bool isLaneOp =
false;
15846 bool hasAlignment =
true;
15847 unsigned NewOpc = 0;
15848 unsigned NumVecs = 0;
15849 if (
Target.isIntrinsic) {
15850 unsigned IntNo =
N->getConstantOperandVal(1);
15854 case Intrinsic::arm_neon_vld1:
15858 case Intrinsic::arm_neon_vld2:
15862 case Intrinsic::arm_neon_vld3:
15866 case Intrinsic::arm_neon_vld4:
15870 case Intrinsic::arm_neon_vld1x2:
15873 hasAlignment =
false;
15875 case Intrinsic::arm_neon_vld1x3:
15878 hasAlignment =
false;
15880 case Intrinsic::arm_neon_vld1x4:
15883 hasAlignment =
false;
15885 case Intrinsic::arm_neon_vld2dup:
15889 case Intrinsic::arm_neon_vld3dup:
15893 case Intrinsic::arm_neon_vld4dup:
15897 case Intrinsic::arm_neon_vld2lane:
15902 case Intrinsic::arm_neon_vld3lane:
15907 case Intrinsic::arm_neon_vld4lane:
15912 case Intrinsic::arm_neon_vst1:
15917 case Intrinsic::arm_neon_vst2:
15918 NewOpc = ARMISD::VST2_UPD;
15922 case Intrinsic::arm_neon_vst3:
15927 case Intrinsic::arm_neon_vst4:
15928 NewOpc = ARMISD::VST4_UPD;
15932 case Intrinsic::arm_neon_vst2lane:
15938 case Intrinsic::arm_neon_vst3lane:
15944 case Intrinsic::arm_neon_vst4lane:
15950 case Intrinsic::arm_neon_vst1x2:
15954 hasAlignment =
false;
15956 case Intrinsic::arm_neon_vst1x3:
15960 hasAlignment =
false;
15962 case Intrinsic::arm_neon_vst1x4:
15966 hasAlignment =
false;
15971 switch (
N->getOpcode()) {
16007 VecTy =
N->getValueType(0);
16008 }
else if (
Target.isIntrinsic) {
16009 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16012 "Node has to be a load, a store, or an intrinsic!");
16013 VecTy =
N->getOperand(1).getValueType();
16021 if (isLaneOp || isVLDDUPOp)
16024 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16030 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16039 EVT AlignedVecTy = VecTy;
16059 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16060 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16071 Alignment =
Align(1);
16077 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16079 for (n = 0; n < NumResultVecs; ++n)
16080 Tys[n] = AlignedVecTy;
16081 Tys[n++] = MVT::i32;
16082 Tys[n] = MVT::Other;
16087 Ops.push_back(
N->getOperand(0));
16088 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16093 Ops.push_back(StN->getValue());
16097 unsigned LastOperand =
16098 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16099 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16100 Ops.push_back(
N->getOperand(i));
16108 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16119 for (
unsigned i = 0; i < NumResultVecs; ++i)
16124 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16125 SDValue &LdVal = NewResults[0];
16161 switch (
N->getOpcode()) {
16165 *Ptr =
N->getOperand(0);
16166 *CInc =
N->getOperand(1);
16173 *Ptr =
N->getOperand(1);
16174 *CInc =
N->getOperand(2);
16201 SDValue Addr =
N->getOperand(AddrOpIdx);
16212 unsigned ConstInc =
16217 if (BaseUpdates.
size() >= MaxBaseUpdates)
16238 unsigned UserOffset =
16241 if (!UserOffset || UserOffset <=
Offset)
16244 unsigned NewConstInc = UserOffset -
Offset;
16247 if (BaseUpdates.
size() >= MaxBaseUpdates)
16255 unsigned NumValidUpd = BaseUpdates.
size();
16256 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16267 return LHS.ConstInc <
RHS.ConstInc;
16296 unsigned IntNo =
N->getConstantOperandVal(1);
16297 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16299 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16322 bool isLoadOp =
true;
16323 unsigned NewOpc = 0;
16324 unsigned NumVecs = 0;
16328 case Intrinsic::arm_mve_vld2q:
16332 case Intrinsic::arm_mve_vld4q:
16336 case Intrinsic::arm_mve_vst2q:
16337 NewOpc = ARMISD::VST2_UPD;
16341 case Intrinsic::arm_mve_vst4q:
16342 NewOpc = ARMISD::VST4_UPD;
16351 VecTy =
N->getValueType(0);
16353 VecTy =
N->getOperand(3).getValueType();
16367 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16369 for (n = 0; n < NumResultVecs; ++n)
16371 Tys[n++] = MVT::i32;
16372 Tys[n] = MVT::Other;
16377 Ops.push_back(
N->getOperand(0));
16378 Ops.push_back(
N->getOperand(2));
16379 Ops.push_back(Inc);
16381 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16382 Ops.push_back(
N->getOperand(i));
16389 for (
unsigned i = 0; i < NumResultVecs; ++i)
16408 EVT VT =
N->getValueType(0);
16414 SDNode *VLD =
N->getOperand(0).getNode();
16417 unsigned NumVecs = 0;
16418 unsigned NewOpc = 0;
16420 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16423 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16426 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16438 if (
Use.getResNo() == NumVecs)
16441 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16442 VLDLaneNo !=
User->getConstantOperandVal(1))
16449 for (n = 0; n < NumVecs; ++n)
16451 Tys[n] = MVT::Other;
16461 unsigned ResNo =
Use.getResNo();
16463 if (ResNo == NumVecs)
16470 std::vector<SDValue> VLDDupResults;
16471 for (
unsigned n = 0; n < NumVecs; ++n)
16485 EVT VT =
N->getValueType(0);
16488 if (Subtarget->hasMVEIntegerOps()) {
16492 ExtractVT = MVT::i32;
16494 N->getOperand(0),
N->getOperand(1));
16506 Op =
Op.getOperand(0);
16507 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16511 unsigned EltSize =
Op.getScalarValueSizeInBits();
16513 unsigned Imm =
Op.getConstantOperandVal(0);
16529 if (Subtarget->hasMVEIntegerOps()) {
16532 if (
Op.getValueType() == MVT::f32)
16533 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16535 else if (
Op.getValueType() == MVT::f16)
16536 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16537 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16540 if (!Subtarget->hasNEON())
16547 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16548 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16549 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16554 LD->getMemoryVT(), LD->getMemOperand());
16565 EVT VT =
N->getValueType(0);
16587 assert(StVT != VT &&
"Cannot truncate to the same type");
16597 if (0 != (NumElems * FromEltSz) % ToEltSz)
16600 unsigned SizeRatio = FromEltSz / ToEltSz;
16605 NumElems * SizeRatio);
16611 for (
unsigned i = 0; i < NumElems; ++i)
16625 MVT StoreType = MVT::i8;
16627 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16647 for (
unsigned I = 0;
I <
E;
I++) {
16678 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16681 unsigned NumElements = 4;
16698 unsigned Off0 = Rev ? NumElts : 0;
16699 unsigned Off1 = Rev ? 0 : NumElts;
16701 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16702 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16704 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16712 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16732 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16743 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16747 NewToVT, Alignment, MMOFlags, AAInfo);
16780 unsigned NewOffset =
16788 NewToVT, Alignment, MMOFlags, AAInfo);
16810 {Extract.getOperand(0), Extract.getOperand(1)});
16841 if (Subtarget->hasNEON())
16845 if (Subtarget->hasMVEFloatOps())
16849 if (Subtarget->hasMVEIntegerOps()) {
16924 if (!Subtarget->hasNEON())
16928 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16936 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16938 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16939 uint32_t IntBits = IntTy.getSizeInBits();
16940 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16941 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16952 if (
C == -1 ||
C == 0 ||
C > 32)
16957 unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16958 Intrinsic::arm_neon_vcvtfp2fxu;
16961 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16964 if (IntBits < FloatBits)
16972 if (!Subtarget->hasMVEFloatOps())
16980 EVT VT =
N->getValueType(0);
16985 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16987 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
16989 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16990 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16992 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17005 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17016 EVT VT =
N->getValueType(0);
17019 if (!
N->getFlags().hasAllowReassociation())
17026 unsigned Opc =
A.getConstantOperandVal(0);
17027 if (
Opc != Intrinsic::arm_mve_vcmlaq)
17032 A.getOperand(3),
A.getOperand(4));
17064 if (!Subtarget->hasNEON())
17068 unsigned OpOpcode =
Op.getNode()->getOpcode();
17069 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17073 SDValue ConstVec =
N->getOperand(1);
17077 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17079 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17080 uint32_t IntBits = IntTy.getSizeInBits();
17081 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17082 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17102 int32_t
C = IntVal.exactLogBase2();
17103 if (
C == -1 ||
C == 0 ||
C > 32)
17109 if (IntBits < FloatBits)
17111 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17113 unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17114 : Intrinsic::arm_neon_vcvtfxu2fp;
17122 if (!ST->hasMVEIntegerOps())
17126 EVT ResVT =
N->getValueType(0);
17154 EVT AVT =
A.getValueType();
17160 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17161 EVT AVT =
A.getValueType();
17171 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17172 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17175 if (ExtTypeMatches(
A, ExtTypes))
17176 return ExtendIfNeeded(
A, ExtendCode);
17179 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17189 if (ExtTypeMatches(
A, ExtTypes))
17190 return ExtendIfNeeded(
A, ExtendCode);
17193 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17203 if (ResVT != RetTy)
17206 if (
Mul->getOpcode() == ExtendCode &&
17207 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17209 Mul =
Mul->getOperand(0);
17218 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17219 A = ExtendIfNeeded(
A, ExtendCode);
17220 B = ExtendIfNeeded(
B, ExtendCode);
17225 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17238 if (
Mul->getOpcode() == ExtendCode &&
17239 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17241 Mul =
Mul->getOperand(0);
17250 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17251 A = ExtendIfNeeded(
A, ExtendCode);
17252 B = ExtendIfNeeded(
B, ExtendCode);
17263 EVT VT =
Ops[0].getValueType();
17264 if (VT == MVT::v16i8) {
17265 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17266 "Unexpected illegal long reduction opcode");
17267 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17279 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17292 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17294 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17295 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17297 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17298 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17300 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17303 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17306 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17310 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17313 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17316 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17319 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17322 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17325 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17328 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17330 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17332 return Create64bitNode(ARMISD::VADDLVs, {
A});
17334 return Create64bitNode(ARMISD::VADDLVu, {
A});
17337 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17340 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17343 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17345 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17347 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17349 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17352 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17355 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17362 Op =
Op->getOperand(1);
17364 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17366 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17383 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17385 if (!Shuf || !Shuf->getOperand(1).isUndef())
17390 APInt SetElts(Mask.size(), 0);
17391 for (
int E : Mask) {
17399 if (
N->getNumOperands() != VecOp + 1) {
17401 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17407 if (
Op.getValueType().isVector())
17408 Ops.push_back(
Op.getOperand(0));
17419 unsigned IsTop =
N->getConstantOperandVal(2);
17426 if (Op0->
isUndef() && !IsTop)
17431 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17432 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17440 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17442 APInt Op0DemandedElts =
17443 IsTop ? Op1DemandedElts
17458 unsigned IsTop =
N->getConstantOperandVal(2);
17460 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17461 APInt Op0DemandedElts =
17473 EVT VT =
N->getValueType(0);
17480 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17481 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17485 LHS.getOperand(0),
RHS.getOperand(0));
17500 int ShiftAmt =
C->getSExtValue();
17501 if (ShiftAmt == 0) {
17507 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17508 unsigned NewOpcode =
17509 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17524 unsigned IntNo =
N->getConstantOperandVal(0);
17535 case Intrinsic::arm_neon_vshifts:
17536 case Intrinsic::arm_neon_vshiftu:
17537 case Intrinsic::arm_neon_vrshifts:
17538 case Intrinsic::arm_neon_vrshiftu:
17539 case Intrinsic::arm_neon_vrshiftn:
17540 case Intrinsic::arm_neon_vqshifts:
17541 case Intrinsic::arm_neon_vqshiftu:
17542 case Intrinsic::arm_neon_vqshiftsu:
17543 case Intrinsic::arm_neon_vqshiftns:
17544 case Intrinsic::arm_neon_vqshiftnu:
17545 case Intrinsic::arm_neon_vqshiftnsu:
17546 case Intrinsic::arm_neon_vqrshiftns:
17547 case Intrinsic::arm_neon_vqrshiftnu:
17548 case Intrinsic::arm_neon_vqrshiftnsu: {
17549 EVT VT =
N->getOperand(1).getValueType();
17551 unsigned VShiftOpc = 0;
17554 case Intrinsic::arm_neon_vshifts:
17555 case Intrinsic::arm_neon_vshiftu:
17557 VShiftOpc = ARMISD::VSHLIMM;
17560 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17561 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17562 : ARMISD::VSHRuIMM);
17567 case Intrinsic::arm_neon_vrshifts:
17568 case Intrinsic::arm_neon_vrshiftu:
17573 case Intrinsic::arm_neon_vqshifts:
17574 case Intrinsic::arm_neon_vqshiftu:
17579 case Intrinsic::arm_neon_vqshiftsu:
17584 case Intrinsic::arm_neon_vrshiftn:
17585 case Intrinsic::arm_neon_vqshiftns:
17586 case Intrinsic::arm_neon_vqshiftnu:
17587 case Intrinsic::arm_neon_vqshiftnsu:
17588 case Intrinsic::arm_neon_vqrshiftns:
17589 case Intrinsic::arm_neon_vqrshiftnu:
17590 case Intrinsic::arm_neon_vqrshiftnsu:
17602 case Intrinsic::arm_neon_vshifts:
17603 case Intrinsic::arm_neon_vshiftu:
17606 case Intrinsic::arm_neon_vrshifts:
17607 VShiftOpc = ARMISD::VRSHRsIMM;
17609 case Intrinsic::arm_neon_vrshiftu:
17610 VShiftOpc = ARMISD::VRSHRuIMM;
17612 case Intrinsic::arm_neon_vrshiftn:
17613 VShiftOpc = ARMISD::VRSHRNIMM;
17615 case Intrinsic::arm_neon_vqshifts:
17616 VShiftOpc = ARMISD::VQSHLsIMM;
17618 case Intrinsic::arm_neon_vqshiftu:
17619 VShiftOpc = ARMISD::VQSHLuIMM;
17621 case Intrinsic::arm_neon_vqshiftsu:
17622 VShiftOpc = ARMISD::VQSHLsuIMM;
17624 case Intrinsic::arm_neon_vqshiftns:
17625 VShiftOpc = ARMISD::VQSHRNsIMM;
17627 case Intrinsic::arm_neon_vqshiftnu:
17628 VShiftOpc = ARMISD::VQSHRNuIMM;
17630 case Intrinsic::arm_neon_vqshiftnsu:
17631 VShiftOpc = ARMISD::VQSHRNsuIMM;
17633 case Intrinsic::arm_neon_vqrshiftns:
17634 VShiftOpc = ARMISD::VQRSHRNsIMM;
17636 case Intrinsic::arm_neon_vqrshiftnu:
17637 VShiftOpc = ARMISD::VQRSHRNuIMM;
17639 case Intrinsic::arm_neon_vqrshiftnsu:
17640 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17645 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17646 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17649 case Intrinsic::arm_neon_vshiftins: {
17650 EVT VT =
N->getOperand(1).getValueType();
17652 unsigned VShiftOpc = 0;
17655 VShiftOpc = ARMISD::VSLIIMM;
17656 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17657 VShiftOpc = ARMISD::VSRIIMM;
17663 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17664 N->getOperand(1),
N->getOperand(2),
17668 case Intrinsic::arm_neon_vqrshifts:
17669 case Intrinsic::arm_neon_vqrshiftu:
17673 case Intrinsic::arm_neon_vbsl: {
17675 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17676 N->getOperand(2),
N->getOperand(3));
17678 case Intrinsic::arm_mve_vqdmlah:
17679 case Intrinsic::arm_mve_vqdmlash:
17680 case Intrinsic::arm_mve_vqrdmlah:
17681 case Intrinsic::arm_mve_vqrdmlash:
17682 case Intrinsic::arm_mve_vmla_n_predicated:
17683 case Intrinsic::arm_mve_vmlas_n_predicated:
17684 case Intrinsic::arm_mve_vqdmlah_predicated:
17685 case Intrinsic::arm_mve_vqdmlash_predicated:
17686 case Intrinsic::arm_mve_vqrdmlah_predicated:
17687 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17692 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17699 case Intrinsic::arm_mve_minv:
17700 case Intrinsic::arm_mve_maxv:
17701 case Intrinsic::arm_mve_minav:
17702 case Intrinsic::arm_mve_maxav:
17703 case Intrinsic::arm_mve_minv_predicated:
17704 case Intrinsic::arm_mve_maxv_predicated:
17705 case Intrinsic::arm_mve_minav_predicated:
17706 case Intrinsic::arm_mve_maxav_predicated: {
17709 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17716 case Intrinsic::arm_mve_addv: {
17719 bool Unsigned =
N->getConstantOperandVal(2);
17720 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17724 case Intrinsic::arm_mve_addlv:
17725 case Intrinsic::arm_mve_addlv_predicated: {
17728 bool Unsigned =
N->getConstantOperandVal(2);
17729 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17730 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17731 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17734 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17736 Ops.push_back(
N->getOperand(i));
17757 EVT VT =
N->getValueType(0);
17759 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17760 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17761 N->getOperand(0)->hasOneUse()) {
17778 if (AndMask == 255 || AndMask == 65535)
17782 if (MaskedBits > ShiftAmt) {
17797 if (ST->hasMVEIntegerOps())
17802 switch (
N->getOpcode()) {
17808 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17815 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17816 unsigned VShiftOpc =
17817 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17819 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17835 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17838 EVT FromVT = LD->getValueType(0);
17839 EVT ToVT =
N->getValueType(0);
17846 unsigned NumElements = 0;
17847 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17849 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17851 if (NumElements == 0 ||
17861 SDValue BasePtr = LD->getBasePtr();
17862 Align Alignment = LD->getBaseAlign();
17883 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17884 Alignment, MMOFlags, AAInfo);
17890 if (FromEltVT == MVT::f16) {
17893 for (
unsigned i = 0; i < Loads.
size(); i++) {
17895 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
17919 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17923 EVT VT =
N->getValueType(0);
17927 if (VT == MVT::i32 &&
17928 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17933 switch (
N->getOpcode()) {
17936 Opc = ARMISD::VGETLANEs;
17940 Opc = ARMISD::VGETLANEu;
17947 if (ST->hasMVEIntegerOps())
17956 if (ST->hasMVEFloatOps())
17967 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17971 EVT VT =
Op.getValueType();
17974 if (VT != MVT::i32 ||
17987 APInt MaxC = Max.getConstantOperandAPInt(1);
17990 !(MinC + 1).isPowerOf2())
18008 EVT VT =
N->getValueType(0);
18011 if (VT == MVT::i32)
18014 if (!ST->hasMVEIntegerOps())
18020 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18023 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18031 if (VT == MVT::v4i32)
18032 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18034 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18041 MaxC != ~SaturateC)
18046 if (IsSignedSaturate(
N, N0.
getNode())) {
18049 if (VT == MVT::v4i32) {
18050 HalfVT = MVT::v8i16;
18051 ExtVT = MVT::v4i16;
18053 HalfVT = MVT::v16i8;
18068 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18074 if (VT == MVT::v4i32)
18075 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18077 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18086 if (IsUnsignedSaturate(
N)) {
18090 if (VT == MVT::v4i32) {
18091 HalfVT = MVT::v8i16;
18092 ExtConst = 0x0000FFFF;
18094 HalfVT = MVT::v16i8;
18116 const APInt *CV = &
C->getAPIntValue();
18173 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18180 if ((OrCI & Known.
Zero) != OrCI)
18186 EVT VT =
X.getValueType();
18187 unsigned BitInX = AndC->
logBase2();
18195 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18196 BitInY < NumActiveBits; ++BitInY) {
18197 if (OrCI[BitInY] == 0)
18200 Mask.setBit(BitInY);
18201 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18217 switch (
N->getOpcode()) {
18232 if (Const->isZero())
18234 else if (Const->isOne())
18242 unsigned IntOp =
N.getConstantOperandVal(1);
18243 if (IntOp != Intrinsic::test_start_loop_iterations &&
18244 IntOp != Intrinsic::loop_decrement_reg)
18270 bool Negate =
false;
18276 Cond =
N->getOperand(1);
18277 Dest =
N->getOperand(2);
18281 Cond =
N->getOperand(2);
18282 Dest =
N->getOperand(4);
18284 if (!Const->isOne() && !Const->isZero())
18286 Imm = Const->getZExtValue();
18314 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18315 "unsupported condition");
18320 unsigned IntOp =
Int->getConstantOperandVal(1);
18321 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18322 "expected single br user");
18323 SDNode *Br = *
N->user_begin();
18333 if (IntOp == Intrinsic::test_start_loop_iterations) {
18335 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18337 if (IsTrueIfZero(CC, Imm)) {
18339 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18343 UpdateUncondBr(Br, Dest, DAG);
18345 SDValue Ops[] = {Chain, Setup, OtherTarget};
18346 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18358 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18362 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18366 if (
Target == OtherTarget)
18367 UpdateUncondBr(Br, Dest, DAG);
18373 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18382 if (Cmp.getOpcode() != ARMISD::CMPZ)
18387 SDValue LHS = Cmp.getOperand(0);
18388 SDValue RHS = Cmp.getOperand(1);
18397 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18398 LHS->getOperand(0)->hasOneUse() &&
18402 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18414 EVT VT =
N->getValueType(0);
18415 SDValue FalseVal =
N->getOperand(0);
18416 SDValue TrueVal =
N->getOperand(1);
18424 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18431 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18434 if (Cmp.getOpcode() != ARMISD::CMPZ)
18438 SDValue LHS = Cmp.getOperand(0);
18439 SDValue RHS = Cmp.getOperand(1);
18443 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18467 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18468 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18469 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18472 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18477 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18480 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18481 LHS->getOperand(2), LHS->getOperand(3));
18491 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18495 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18497 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18506 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18539 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18551 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18571 const APInt *TrueConst;
18572 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18573 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18574 FalseVal.getOperand(1) == RHS) ||
18578 unsigned ShiftAmount = TrueConst->
logBase2();
18593 if (Known.
Zero == 0xfffffffe)
18596 else if (Known.
Zero == 0xffffff00)
18599 else if (Known.
Zero == 0xffff0000)
18612 EVT DstVT =
N->getValueType(0);
18615 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18616 EVT SrcVT = Src.getValueType();
18618 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18623 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18624 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18625 Src.getValueType().getScalarSizeInBits())
18626 Src = Src.getOperand(0);
18630 EVT SrcVT = Src.getValueType();
18631 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18632 Src.getOpcode() == ARMISD::VMVNIMM ||
18633 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18636 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18650 EVT VT =
N->getValueType(0);
18658 if (
N->getNumOperands() == 2 &&
18662 N->getOperand(0).getOperand(1),
18663 N->getOperand(1).getOperand(0),
18664 N->getOperand(1).getOperand(1));
18667 if (
N->getNumOperands() == 2 &&
18673 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18674 S0->getOperand(1) ==
S1->getOperand(1)) {
18677 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18681 ARMISD::VMOVN,
DL, VT,
18682 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18683 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18687 ARMISD::VMOVN,
DL, VT,
18688 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18689 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18697 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18698 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18699 (Op.getOpcode() == ISD::BITCAST &&
18700 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18703 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18705 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18723 int NumIns =
N->getNumOperands();
18724 assert((NumIns == 2 || NumIns == 4) &&
18725 "Expected 2 or 4 inputs to an MVETrunc");
18727 if (
N->getNumOperands() == 4)
18731 for (
int I = 0;
I < NumIns;
I++) {
18733 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18738 Ptr, MPI, StoreVT,
Align(4));
18753 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18756 EVT FromVT = LD->getMemoryVT();
18757 EVT ToVT =
N->getValueType(0);
18764 unsigned NumElements = 0;
18765 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18767 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18769 assert(NumElements != 0);
18775 LD->getExtensionType() != NewExtType)
18782 SDValue BasePtr = LD->getBasePtr();
18783 Align Alignment = LD->getBaseAlign();
18802 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18803 Alignment, MMOFlags, AAInfo);
18819 EVT VT =
N->getValueType(0);
18821 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18822 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18824 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18826 auto Extend = [&](
SDValue V) {
18835 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
18836 SDValue Ext = Extend(
N->getOperand(0));
18844 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18845 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
18849 auto CheckInregMask = [&](
int Start,
int Offset) {
18851 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18857 if (CheckInregMask(0, 0))
18859 else if (CheckInregMask(0, 1))
18860 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18861 else if (CheckInregMask(0, Mask.size()))
18863 else if (CheckInregMask(0, Mask.size() + 1))
18864 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18869 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18873 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18880 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
18891 int NumOuts =
N->getNumValues();
18892 assert((NumOuts == 2 || NumOuts == 4) &&
18893 "Expected 2 or 4 outputs to an MVEEXT");
18894 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18896 if (
N->getNumOperands() == 4)
18902 StackPtr, MPI,
Align(4));
18905 for (
int I = 0;
I < NumOuts;
I++) {
18907 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18908 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18913 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
18922 switch (
N->getOpcode()) {
18982 case ARMISD::BRCOND:
18986 case ARMISD::CSINC:
18987 case ARMISD::CSINV:
18988 case ARMISD::CSNEG:
19001 case ARMISD::PREDICATE_CAST:
19003 case ARMISD::VECTOR_REG_CAST:
19014 case ARMISD::VADDVs:
19015 case ARMISD::VADDVu:
19016 case ARMISD::VADDLVs:
19017 case ARMISD::VADDLVu:
19018 case ARMISD::VADDLVAs:
19019 case ARMISD::VADDLVAu:
19020 case ARMISD::VMLAVs:
19021 case ARMISD::VMLAVu:
19022 case ARMISD::VMLALVs:
19023 case ARMISD::VMLALVu:
19024 case ARMISD::VMLALVAs:
19025 case ARMISD::VMLALVAu:
19027 case ARMISD::VMOVN:
19029 case ARMISD::VQMOVNs:
19030 case ARMISD::VQMOVNu:
19032 case ARMISD::VQDMULH:
19038 case ARMISD::SMULWB: {
19039 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19045 case ARMISD::SMULWT: {
19046 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19052 case ARMISD::SMLALBB:
19053 case ARMISD::QADD16b:
19054 case ARMISD::QSUB16b:
19055 case ARMISD::UQADD16b:
19056 case ARMISD::UQSUB16b: {
19057 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19064 case ARMISD::SMLALBT: {
19065 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19067 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19074 case ARMISD::SMLALTB: {
19075 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19077 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19084 case ARMISD::SMLALTT: {
19085 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19092 case ARMISD::QADD8b:
19093 case ARMISD::QSUB8b:
19094 case ARMISD::UQADD8b:
19095 case ARMISD::UQSUB8b: {
19096 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19104 if (
N->getOperand(1) ==
N->getOperand(2))
19105 return N->getOperand(1);
19109 switch (
N->getConstantOperandVal(1)) {
19110 case Intrinsic::arm_neon_vld1:
19111 case Intrinsic::arm_neon_vld1x2:
19112 case Intrinsic::arm_neon_vld1x3:
19113 case Intrinsic::arm_neon_vld1x4:
19114 case Intrinsic::arm_neon_vld2:
19115 case Intrinsic::arm_neon_vld3:
19116 case Intrinsic::arm_neon_vld4:
19117 case Intrinsic::arm_neon_vld2lane:
19118 case Intrinsic::arm_neon_vld3lane:
19119 case Intrinsic::arm_neon_vld4lane:
19120 case Intrinsic::arm_neon_vld2dup:
19121 case Intrinsic::arm_neon_vld3dup:
19122 case Intrinsic::arm_neon_vld4dup:
19123 case Intrinsic::arm_neon_vst1:
19124 case Intrinsic::arm_neon_vst1x2:
19125 case Intrinsic::arm_neon_vst1x3:
19126 case Intrinsic::arm_neon_vst1x4:
19127 case Intrinsic::arm_neon_vst2:
19128 case Intrinsic::arm_neon_vst3:
19129 case Intrinsic::arm_neon_vst4:
19130 case Intrinsic::arm_neon_vst2lane:
19131 case Intrinsic::arm_neon_vst3lane:
19132 case Intrinsic::arm_neon_vst4lane:
19134 case Intrinsic::arm_mve_vld2q:
19135 case Intrinsic::arm_mve_vld4q:
19136 case Intrinsic::arm_mve_vst2q:
19137 case Intrinsic::arm_mve_vst4q:
19154 unsigned *
Fast)
const {
19160 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19163 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19165 if (AllowsUnaligned) {
19167 *
Fast = Subtarget->hasV7Ops();
19172 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19176 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19183 if (!Subtarget->hasMVEIntegerOps())
19187 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19188 Ty == MVT::v2i1)) {
19196 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19212 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19213 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19214 Ty == MVT::v2f64) {
19225 const AttributeList &FuncAttributes)
const {
19227 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19228 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19230 if (
Op.size() >= 16 &&
19236 }
else if (
Op.size() >= 8 &&
19253 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19255 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19257 return (SrcBits == 64 && DestBits == 32);
19266 return (SrcBits == 64 && DestBits == 32);
19302 return Subtarget->hasFullFP16();
19309 if (!Subtarget->hasMVEIntegerOps())
19328 if (Ld->isExpandingLoad())
19332 if (Subtarget->hasMVEIntegerOps())
19345 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19377bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19379 if (Subtarget->useSoftFloat())
19388 return Subtarget->hasMVEFloatOps();
19406 unsigned Scale = 1;
19423 if ((V & (Scale - 1)) != 0)
19432 if (VT.
isVector() && Subtarget->hasNEON())
19435 !Subtarget->hasMVEFloatOps())
19438 bool IsNeg =
false;
19444 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19447 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19463 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19469 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19499 default:
return false;
19518 int Scale = AM.
Scale;
19523 default:
return false;
19531 Scale = Scale & ~1;
19532 return Scale == 2 || Scale == 4 || Scale == 8;
19549 if (Scale & 1)
return false;
19556 const int Scale = AM.
Scale;
19566 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19582 switch (AM.
Scale) {
19593 if (Subtarget->isThumb1Only())
19596 if (Subtarget->isThumb2())
19599 int Scale = AM.
Scale;
19601 default:
return false;
19605 if (Scale < 0) Scale = -Scale;
19613 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19626 if (Scale & 1)
return false;
19639 if (!Subtarget->isThumb())
19642 if (Subtarget->isThumb2())
19646 return Imm >= 0 && Imm <= 255;
19656 if (!Subtarget->isThumb())
19658 if (Subtarget->isThumb2())
19661 return AbsImm <= 255;
19696 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19700 int RHSC = (int)
RHS->getZExtValue();
19701 if (RHSC < 0 && RHSC > -256) {
19711 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19714 int RHSC = (int)
RHS->getZExtValue();
19715 if (RHSC < 0 && RHSC > -0x1000) {
19757 int RHSC = (int)
RHS->getZExtValue();
19758 if (RHSC < 0 && RHSC > -0x100) {
19763 }
else if (RHSC > 0 && RHSC < 0x100) {
19774 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19785 bool CanChangeType = isLE && !IsMasked;
19788 int RHSC = (int)
RHS->getZExtValue();
19790 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19791 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19796 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19807 if (VT == MVT::v4i16) {
19808 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19810 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19811 if (IsInRange(RHSC, 0x80, 1))
19813 }
else if (Alignment >= 4 &&
19814 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19815 IsInRange(RHSC, 0x80, 4))
19817 else if (Alignment >= 2 &&
19818 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19819 IsInRange(RHSC, 0x80, 2))
19821 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19834 if (Subtarget->isThumb1Only())
19841 bool isSEXTLoad =
false;
19842 bool IsMasked =
false;
19844 Ptr = LD->getBasePtr();
19845 VT = LD->getMemoryVT();
19846 Alignment = LD->getAlign();
19847 AS = LD->getAddressSpace();
19850 Ptr = ST->getBasePtr();
19851 VT = ST->getMemoryVT();
19852 Alignment = ST->getAlign();
19853 AS = ST->getAddressSpace();
19855 Ptr = LD->getBasePtr();
19856 VT = LD->getMemoryVT();
19857 Alignment = LD->getAlign();
19858 AS = LD->getAddressSpace();
19862 Ptr = ST->getBasePtr();
19863 VT = ST->getMemoryVT();
19864 Alignment = ST->getAlign();
19865 AS = ST->getAddressSpace();
19880 bool isLegal =
false;
19882 isLegal = Subtarget->hasMVEIntegerOps() &&
19884 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19885 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19887 if (Subtarget->isThumb2())
19912 bool isSEXTLoad =
false, isNonExt;
19913 bool IsMasked =
false;
19915 VT = LD->getMemoryVT();
19916 Ptr = LD->getBasePtr();
19917 Alignment = LD->getAlign();
19921 VT = ST->getMemoryVT();
19922 Ptr = ST->getBasePtr();
19923 Alignment = ST->getAlign();
19924 isNonExt = !ST->isTruncatingStore();
19926 VT = LD->getMemoryVT();
19927 Ptr = LD->getBasePtr();
19928 Alignment = LD->getAlign();
19933 VT = ST->getMemoryVT();
19934 Ptr = ST->getBasePtr();
19935 Alignment = ST->getAlign();
19936 isNonExt = !ST->isTruncatingStore();
19941 if (Subtarget->isThumb1Only()) {
19944 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19945 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19948 if (!RHS || RHS->getZExtValue() != 4)
19950 if (Alignment <
Align(4))
19954 Base =
Op->getOperand(0);
19960 bool isLegal =
false;
19962 isLegal = Subtarget->hasMVEIntegerOps() &&
19967 if (Subtarget->isThumb2())
19981 !Subtarget->isThumb2())
19995 const APInt &DemandedElts,
19997 unsigned Depth)
const {
20000 switch (
Op.getOpcode()) {
20007 if (
Op.getResNo() == 0) {
20018 case ARMISD::CMOV: {
20033 case Intrinsic::arm_ldaex:
20034 case Intrinsic::arm_ldrex: {
20042 case ARMISD::BFI: {
20049 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20050 Known.
Zero &= Mask;
20054 case ARMISD::VGETLANEs:
20055 case ARMISD::VGETLANEu: {
20056 const SDValue &SrcSV =
Op.getOperand(0);
20062 "VGETLANE index out of bounds");
20067 EVT VT =
Op.getValueType();
20073 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20074 Known = Known.
sext(DstSz);
20076 Known = Known.
zext(DstSz);
20081 case ARMISD::VMOVrh: {
20084 Known = KnownOp.
zext(32);
20087 case ARMISD::CSINC:
20088 case ARMISD::CSINV:
20089 case ARMISD::CSNEG: {
20097 if (
Op.getOpcode() == ARMISD::CSINC)
20100 else if (
Op.getOpcode() == ARMISD::CSINV)
20102 else if (
Op.getOpcode() == ARMISD::CSNEG)
20109 case ARMISD::VORRIMM:
20110 case ARMISD::VBICIMM: {
20111 unsigned Encoded =
Op.getConstantOperandVal(1);
20112 unsigned DecEltBits = 0;
20115 unsigned EltBits =
Op.getScalarValueSizeInBits();
20116 if (EltBits != DecEltBits) {
20125 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20126 APInt Imm(DecEltBits, DecodedVal);
20128 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20129 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20147 EVT VT =
Op.getValueType();
20153 assert(VT == MVT::i32 &&
"Unexpected integer type");
20160 unsigned Mask =
C->getZExtValue();
20163 unsigned ShrunkMask = Mask & Demanded;
20164 unsigned ExpandedMask = Mask | ~Demanded;
20168 if (ShrunkMask == 0)
20174 if (ExpandedMask == ~0U)
20177 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20178 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20180 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20181 if (NewMask == Mask)
20190 if (IsLegalMask(0xFF))
20191 return UseMask(0xFF);
20194 if (IsLegalMask(0xFFFF))
20195 return UseMask(0xFFFF);
20199 if (ShrunkMask < 256)
20200 return UseMask(ShrunkMask);
20204 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20205 return UseMask(ExpandedMask);
20220 unsigned Depth)
const {
20221 unsigned Opc =
Op.getOpcode();
20225 case ARMISD::LSRL: {
20229 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20231 unsigned ShAmt =
Op->getConstantOperandVal(2);
20241 case ARMISD::VBICIMM: {
20243 unsigned ModImm =
Op.getConstantOperandVal(1);
20244 unsigned EltBits = 0;
20246 if ((OriginalDemandedBits & Mask) == 0)
20252 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20267 if (!Subtarget->hasVFP2Base())
20271 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20283 unsigned S = Constraint.
size();
20285 switch (Constraint[0]) {
20297 }
else if (S == 2) {
20298 switch (Constraint[0]) {
20315 Value *CallOperandVal =
info.CallOperandVal;
20318 if (!CallOperandVal)
20322 switch (*constraint) {
20328 if (Subtarget->isThumb())
20343 if (PR == 0 || VT == MVT::Other)
20345 if (ARM::SPRRegClass.
contains(PR))
20346 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20347 if (ARM::DPRRegClass.
contains(PR))
20352using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20356 switch (Constraint.
size()) {
20359 switch (Constraint[0]) {
20361 if (Subtarget->isThumb())
20362 return RCPair(0U, &ARM::tGPRRegClass);
20363 return RCPair(0U, &ARM::GPRRegClass);
20365 if (Subtarget->isThumb())
20366 return RCPair(0U, &ARM::hGPRRegClass);
20369 if (Subtarget->isThumb1Only())
20370 return RCPair(0U, &ARM::tGPRRegClass);
20371 return RCPair(0U, &ARM::GPRRegClass);
20373 if (VT == MVT::Other)
20375 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20376 return RCPair(0U, &ARM::SPRRegClass);
20378 return RCPair(0U, &ARM::DPRRegClass);
20380 return RCPair(0U, &ARM::QPRRegClass);
20383 if (VT == MVT::Other)
20385 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20386 return RCPair(0U, &ARM::SPR_8RegClass);
20388 return RCPair(0U, &ARM::DPR_8RegClass);
20390 return RCPair(0U, &ARM::QPR_8RegClass);
20393 if (VT == MVT::Other)
20395 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20396 return RCPair(0U, &ARM::SPRRegClass);
20398 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20400 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20406 if (Constraint[0] ==
'T') {
20407 switch (Constraint[1]) {
20411 return RCPair(0U, &ARM::tGPREvenRegClass);
20413 return RCPair(0U, &ARM::tGPROddRegClass);
20422 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20423 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20426 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20427 return std::make_pair(
unsigned(ARM::LR),
getRegClassFor(MVT::i32));
20431 return {0,
nullptr};
20439 std::vector<SDValue> &
Ops,
20444 if (Constraint.
size() != 1)
20447 char ConstraintLetter = Constraint[0];
20448 switch (ConstraintLetter) {
20451 case 'I':
case 'J':
case 'K':
case 'L':
20452 case 'M':
case 'N':
case 'O':
20457 int64_t CVal64 =
C->getSExtValue();
20458 int CVal = (int) CVal64;
20461 if (CVal != CVal64)
20464 switch (ConstraintLetter) {
20468 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20469 if (CVal >= 0 && CVal <= 65535)
20473 if (Subtarget->isThumb1Only()) {
20476 if (CVal >= 0 && CVal <= 255)
20478 }
else if (Subtarget->isThumb2()) {
20492 if (Subtarget->isThumb1Only()) {
20497 if (CVal >= -255 && CVal <= -1)
20503 if (CVal >= -4095 && CVal <= 4095)
20509 if (Subtarget->isThumb1Only()) {
20516 }
else if (Subtarget->isThumb2()) {
20536 if (Subtarget->isThumb1Only()) {
20539 if (CVal >= -7 && CVal < 7)
20541 }
else if (Subtarget->isThumb2()) {
20561 if (Subtarget->isThumb1Only()) {
20564 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20570 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20576 if (Subtarget->isThumb1Only()) {
20578 if (CVal >= 0 && CVal <= 31)
20584 if (Subtarget->isThumb1Only()) {
20587 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20596 if (Result.getNode()) {
20597 Ops.push_back(Result);
20607 "Unhandled Opcode in getDivRemLibcall");
20613 case MVT::i8: LC = isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20614 case MVT::i16: LC = isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20615 case MVT::i32: LC = isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20616 case MVT::i64: LC = isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20625 "Unhandled Opcode in getDivRemArgList");
20629 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20630 EVT ArgVT =
N->getOperand(i).getValueType();
20633 Entry.IsSExt = isSigned;
20634 Entry.IsZExt = !isSigned;
20635 Args.push_back(Entry);
20643 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20644 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20645 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20646 "Register-based DivRem lowering only");
20647 unsigned Opcode =
Op->getOpcode();
20649 "Invalid opcode for Div/Rem lowering");
20651 EVT VT =
Op->getValueType(0);
20673 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20674 : Subtarget->hasDivideInARMMode();
20675 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20676 Op->getSimpleValueType(0) == MVT::i32) {
20678 const SDValue Dividend =
Op->getOperand(0);
20679 const SDValue Divisor =
Op->getOperand(1);
20680 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20684 SDValue Values[2] = {Div, Rem};
20703 if (
getTM().getTargetTriple().isOSWindows())
20706 TargetLowering::CallLoweringInfo CLI(DAG);
20710 Callee, std::move(Args))
20715 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20716 return CallInfo.first;
20722 EVT VT =
N->getValueType(0);
20728 Result[0], Result[1]);
20732 std::vector<Type*> RetTyParams;
20733 Type *RetTyElement;
20743 RetTyParams.push_back(RetTyElement);
20744 RetTyParams.push_back(RetTyElement);
20754 bool isSigned =
N->getOpcode() ==
ISD::SREM;
20759 if (
getTM().getTargetTriple().isOSWindows())
20766 Callee, std::move(Args))
20770 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20773 SDNode *ResNode = CallResult.first.getNode();
20780 assert(
getTM().getTargetTriple().isOSWindows() &&
20781 "unsupported target platform");
20789 "no-stack-arg-probe")) {
20793 Chain =
SP.getValue(1);
20810 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20811 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
20821 bool IsStrict =
Op->isStrictFPOpcode();
20822 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20823 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20825 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20826 "Unexpected type for custom-lowering FP_EXTEND");
20828 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20829 "With both FP DP and 16, any FP conversion is legal!");
20831 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20832 "With FP16, 16 to 32 conversion is legal!");
20835 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20840 Loc,
Op.getValueType(), SrcVal);
20855 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20856 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20857 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20858 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20862 {DstVT, MVT::Other}, {Chain, SrcVal});
20869 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20870 "Unexpected type for custom-lowering FP_EXTEND");
20871 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20876 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20880 bool IsStrict =
Op->isStrictFPOpcode();
20882 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20884 EVT DstVT =
Op.getValueType();
20885 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20888 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20889 "Unexpected type for custom-lowering FP_ROUND");
20891 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20892 "With both FP DP and 16, any FP conversion is legal!");
20897 if (SrcSz == 32 && Subtarget->hasFP16())
20902 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20903 "Unexpected type for custom-lowering FP_ROUND");
20907 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20919 if (v == 0xffffffff)
20931 bool ForCodeSize)
const {
20932 if (!Subtarget->hasVFP3Base())
20934 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20936 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20939 if (VT == MVT::f32)
20941 if (VT == MVT::f64 && Subtarget->hasFP64())
20954 case Intrinsic::arm_neon_vld1:
20955 case Intrinsic::arm_neon_vld2:
20956 case Intrinsic::arm_neon_vld3:
20957 case Intrinsic::arm_neon_vld4:
20958 case Intrinsic::arm_neon_vld2lane:
20959 case Intrinsic::arm_neon_vld3lane:
20960 case Intrinsic::arm_neon_vld4lane:
20961 case Intrinsic::arm_neon_vld2dup:
20962 case Intrinsic::arm_neon_vld3dup:
20963 case Intrinsic::arm_neon_vld4dup: {
20966 auto &
DL =
I.getDataLayout();
20967 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20969 Info.ptrVal =
I.getArgOperand(0);
20971 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20978 case Intrinsic::arm_neon_vld1x2:
20979 case Intrinsic::arm_neon_vld1x3:
20980 case Intrinsic::arm_neon_vld1x4: {
20983 auto &
DL =
I.getDataLayout();
20984 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20986 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20988 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20994 case Intrinsic::arm_neon_vst1:
20995 case Intrinsic::arm_neon_vst2:
20996 case Intrinsic::arm_neon_vst3:
20997 case Intrinsic::arm_neon_vst4:
20998 case Intrinsic::arm_neon_vst2lane:
20999 case Intrinsic::arm_neon_vst3lane:
21000 case Intrinsic::arm_neon_vst4lane: {
21003 auto &
DL =
I.getDataLayout();
21004 unsigned NumElts = 0;
21005 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21006 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21009 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21012 Info.ptrVal =
I.getArgOperand(0);
21014 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21021 case Intrinsic::arm_neon_vst1x2:
21022 case Intrinsic::arm_neon_vst1x3:
21023 case Intrinsic::arm_neon_vst1x4: {
21026 auto &
DL =
I.getDataLayout();
21027 unsigned NumElts = 0;
21028 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21029 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21032 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21035 Info.ptrVal =
I.getArgOperand(0);
21037 Info.align =
I.getParamAlign(0).valueOrOne();
21043 case Intrinsic::arm_mve_vld2q:
21044 case Intrinsic::arm_mve_vld4q: {
21048 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21050 Info.ptrVal =
I.getArgOperand(0);
21058 case Intrinsic::arm_mve_vst2q:
21059 case Intrinsic::arm_mve_vst4q: {
21062 Type *VecTy =
I.getArgOperand(1)->getType();
21063 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21065 Info.ptrVal =
I.getArgOperand(0);
21073 case Intrinsic::arm_mve_vldr_gather_base:
21074 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21076 Info.ptrVal =
nullptr;
21078 Info.align =
Align(1);
21083 case Intrinsic::arm_mve_vldr_gather_base_wb:
21084 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21086 Info.ptrVal =
nullptr;
21087 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21088 Info.align =
Align(1);
21093 case Intrinsic::arm_mve_vldr_gather_offset:
21094 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21096 Info.ptrVal =
nullptr;
21101 Info.align =
Align(1);
21106 case Intrinsic::arm_mve_vstr_scatter_base:
21107 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21109 Info.ptrVal =
nullptr;
21110 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21111 Info.align =
Align(1);
21116 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21117 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21119 Info.ptrVal =
nullptr;
21120 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21121 Info.align =
Align(1);
21126 case Intrinsic::arm_mve_vstr_scatter_offset:
21127 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21129 Info.ptrVal =
nullptr;
21134 Info.align =
Align(1);
21139 case Intrinsic::arm_ldaex:
21140 case Intrinsic::arm_ldrex: {
21141 auto &
DL =
I.getDataLayout();
21142 Type *ValTy =
I.getParamElementType(0);
21145 Info.ptrVal =
I.getArgOperand(0);
21147 Info.align =
DL.getABITypeAlign(ValTy);
21152 case Intrinsic::arm_stlex:
21153 case Intrinsic::arm_strex: {
21154 auto &
DL =
I.getDataLayout();
21155 Type *ValTy =
I.getParamElementType(1);
21158 Info.ptrVal =
I.getArgOperand(1);
21160 Info.align =
DL.getABITypeAlign(ValTy);
21165 case Intrinsic::arm_stlexd:
21166 case Intrinsic::arm_strexd:
21168 Info.memVT = MVT::i64;
21169 Info.ptrVal =
I.getArgOperand(2);
21171 Info.align =
Align(8);
21176 case Intrinsic::arm_ldaexd:
21177 case Intrinsic::arm_ldrexd:
21179 Info.memVT = MVT::i64;
21180 Info.ptrVal =
I.getArgOperand(0);
21182 Info.align =
Align(8);
21196 assert(Ty->isIntegerTy());
21198 unsigned Bits = Ty->getPrimitiveSizeInBits();
21199 if (Bits == 0 || Bits > 32)
21205 unsigned Index)
const {
21215 if (!Subtarget->hasDataBarrier()) {
21219 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21220 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21221 Builder.getInt32(0), Builder.getInt32(7),
21222 Builder.getInt32(10), Builder.getInt32(5)};
21223 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
21233 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
21254 if (Subtarget->preferISHSTBarriers())
21287 bool has64BitAtomicStore;
21288 if (Subtarget->isMClass())
21289 has64BitAtomicStore =
false;
21290 else if (Subtarget->isThumb())
21291 has64BitAtomicStore = Subtarget->hasV7Ops();
21293 has64BitAtomicStore = Subtarget->hasV6Ops();
21295 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21309 bool has64BitAtomicLoad;
21310 if (Subtarget->isMClass())
21311 has64BitAtomicLoad =
false;
21312 else if (Subtarget->isThumb())
21313 has64BitAtomicLoad = Subtarget->hasV7Ops();
21315 has64BitAtomicLoad = Subtarget->hasV6Ops();
21331 if (Subtarget->isMClass())
21332 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21333 else if (Subtarget->isThumb())
21334 hasAtomicRMW = Subtarget->hasV7Ops();
21336 hasAtomicRMW = Subtarget->hasV6Ops();
21337 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21361 bool HasAtomicCmpXchg;
21362 if (Subtarget->isMClass())
21363 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21364 else if (Subtarget->isThumb())
21365 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21367 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21369 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21376 return InsertFencesForAtomic;
21381 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21387 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21388 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21390 RTLIB::LibcallImpl SecurityCookieVar =
21391 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21392 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21393 SecurityCookieVar != RTLIB::Unsupported) {
21404 F->addParamAttr(0, Attribute::AttrKind::InReg);
21411 unsigned &
Cost)
const {
21413 if (!Subtarget->hasNEON())
21442 unsigned Opcode =
Op.getOpcode();
21444 case ARMISD::VORRIMM:
21445 case ARMISD::VBICIMM:
21453 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21457 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21462 if (!Subtarget->hasV7Ops())
21468 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21470 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21478 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21487 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21493 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21495 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21498 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21500 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21501 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21502 if (!Subtarget->isLittle())
21504 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21505 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21506 return Builder.CreateOr(
21507 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21511 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21512 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21515 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21516 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21521 if (!Subtarget->hasV7Ops())
21523 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21529 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21537 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21541 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21542 if (!Subtarget->isLittle())
21544 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21547 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21551 CallInst *CI = Builder.CreateCall(
21552 Strex, {Builder.CreateZExtOrBitCast(
21562 return Subtarget->isMClass();
21570 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21577 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21580 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21588 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21596 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21599 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21604 if (Subtarget->hasNEON() && VecSize == 64)
21606 return VecSize % 128 == 0;
21610 if (Subtarget->hasNEON())
21612 if (Subtarget->hasMVEIntegerOps())
21632 "Invalid interleave factor");
21633 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21635 "Unmatched number of shufflevectors and indices");
21640 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21643 Type *EltTy = VecTy->getElementType();
21646 Align Alignment = LI->getAlign();
21664 Value *BaseAddr = LI->getPointerOperand();
21666 if (NumLoads > 1) {
21670 VecTy->getNumElements() / NumLoads);
21676 if (Subtarget->hasNEON()) {
21677 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21678 Type *Tys[] = {VecTy, PtrTy};
21679 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21680 Intrinsic::arm_neon_vld3,
21681 Intrinsic::arm_neon_vld4};
21684 Ops.push_back(BaseAddr);
21685 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21687 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21690 assert((Factor == 2 || Factor == 4) &&
21691 "expected interleave factor of 2 or 4 for MVE");
21693 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21694 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21695 Type *Tys[] = {VecTy, PtrTy};
21698 Ops.push_back(BaseAddr);
21699 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21709 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21713 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21714 VecTy->getNumElements() * Factor);
21720 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21722 unsigned Index = Indices[i];
21724 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21728 SubVec = Builder.CreateIntToPtr(
21732 SubVecs[SV].push_back(SubVec);
21741 auto &SubVec = SubVecs[SVI];
21744 SVI->replaceAllUsesWith(WideVec);
21780 const APInt &GapMask)
const {
21782 "Invalid interleave factor");
21787 "Unexpected mask on store");
21790 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21792 unsigned LaneLen = VecTy->getNumElements() / Factor;
21793 Type *EltTy = VecTy->getElementType();
21797 Align Alignment =
SI->getAlign();
21814 Type *IntTy =
DL.getIntPtrType(EltTy);
21819 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21820 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21826 Value *BaseAddr =
SI->getPointerOperand();
21828 if (NumStores > 1) {
21831 LaneLen /= NumStores;
21841 if (Subtarget->hasNEON()) {
21842 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21843 Intrinsic::arm_neon_vst3,
21844 Intrinsic::arm_neon_vst4};
21845 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21846 Type *Tys[] = {PtrTy, SubVecTy};
21849 Ops.push_back(BaseAddr);
21851 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21852 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21854 assert((Factor == 2 || Factor == 4) &&
21855 "expected interleave factor of 2 or 4 for MVE");
21857 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21858 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21859 Type *Tys[] = {PtrTy, SubVecTy};
21862 Ops.push_back(BaseAddr);
21864 for (
unsigned F = 0;
F < Factor;
F++) {
21865 Ops.push_back(Builder.getInt32(
F));
21866 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21872 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21875 if (StoreCount > 0)
21876 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21877 BaseAddr, LaneLen * Factor);
21882 for (
unsigned i = 0; i < Factor; i++) {
21883 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21884 if (Mask[IdxI] >= 0) {
21885 Shuffles.
push_back(Builder.CreateShuffleVector(
21888 unsigned StartMask = 0;
21889 for (
unsigned j = 1; j < LaneLen; j++) {
21890 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21891 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21892 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21902 Shuffles.
push_back(Builder.CreateShuffleVector(
21923 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21927 Members += SubMembers;
21933 Members += SubMembers * AT->getNumElements();
21934 }
else if (Ty->isFloatTy()) {
21939 }
else if (Ty->isDoubleTy()) {
21951 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21953 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21955 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21968 return (Members > 0 && Members <= 4);
21974 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21976 return ABITypeAlign;
21981 assert(StackAlign &&
"data layout string is missing stack alignment");
21982 return std::min(ABITypeAlign, *StackAlign);
21991 if (getEffectiveCallingConv(CallConv, isVarArg) !=
22000 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
22001 return IsHA || IsIntArray;
22005 const Constant *PersonalityFn)
const {
22013 const Constant *PersonalityFn)
const {
22026void ARMTargetLowering::insertCopiesSplitCSR(
22030 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22040 RC = &ARM::GPRRegClass;
22041 else if (ARM::DPRRegClass.
contains(*
I))
22042 RC = &ARM::DPRRegClass;
22052 assert(Entry->getParent()->getFunction().hasFnAttribute(
22053 Attribute::NoUnwind) &&
22054 "Function should be nounwind in insertCopiesSplitCSR!");
22055 Entry->addLiveIn(*
I);
22060 for (
auto *Exit : Exits)
22062 TII->get(TargetOpcode::COPY), *
I)
22073 return Subtarget->hasMVEIntegerOps();
22083 unsigned NumElements = VTy->getNumElements();
22090 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22091 return Subtarget->hasMVEFloatOps();
22096 return Subtarget->hasMVEIntegerOps() &&
22097 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22098 ScalarTy->isIntegerTy(32));
22102 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22113 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22115 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22117 if (TyWidth > 128) {
22118 int Stride = Ty->getNumElements() / 2;
22122 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22124 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22125 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22126 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22127 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22128 Value *LowerSplitAcc =
nullptr;
22129 Value *UpperSplitAcc =
nullptr;
22132 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22133 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22137 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22139 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22141 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22142 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22149 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22152 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22154 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22155 {ConstRotation, InputB, InputA});
22160 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22163 ConstRotation = ConstantInt::get(IntTy, 0);
22165 ConstRotation = ConstantInt::get(IntTy, 1);
22167 if (!ConstRotation)
22170 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22171 {ConstHalving, ConstRotation, InputA, InputB});
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static SDValue carryFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG, bool Invert)
static SDValue overflowFlagToValue(SDValue Glue, EVT VT, SelectionDAG &DAG)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue valueToCarryFlag(SDValue Value, SelectionDAG &DAG, bool Invert)
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static bool isSafeSignedCMN(SDValue Op, SelectionDAG &DAG)
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static SDValue matchCSET(unsigned &Opcode, bool &InvertCond, SDValue TrueVal, SDValue FalseVal, const ARMSubtarget *Subtarget)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getInvertedARMCondCode(SDValue ARMcc, SelectionDAG &DAG)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
cl::opt< unsigned > ArmMaxBaseUpdatesToCheck("arm-max-base-updates-to-check", cl::Hidden, cl::desc("Maximum number of base-updates to check generating postindex."), cl::init(64))
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static SDValue LowerADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG, unsigned Opcode, bool IsSigned)
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static int getNegationCost(SDValue Op)
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static 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 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...
StringRef getInternalSymbolPrefix() const
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
iterator find(const_arg_type_t< KeyT > Val)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const GlobalValue * getGlobal() const
bool hasExternalWeakLinkage() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
@ InternalLinkage
Rename collisions when linking (static functions).
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool 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,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
This class is used to represent an MLOAD node.
This class is used to represent an MSTORE node.
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
void setFlags(SDNodeFlags NewFlags)
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
unsigned getNumOperands() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
const LibcallLoweringInfo & getLibcalls() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
This instruction constructs a fixed permutation of two input vectors.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
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...
@ SADDO_CARRY
Carry-using overflow-aware nodes for multiple precision addition and subtraction.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ SjLj
setjmp/longjmp based exceptions
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
FunctionAddr VTableAddr uintptr_t uintptr_t Data
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
bool isUnknown() const
Returns true if we don't know any bits.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)